Laggy behavior shooting ball on soccer game, maybe wrong design

Hi, currently I’m working on a soccer game and I already made a lot of the game engine. Essentially when I shoot the ball from the client I send an event to the server and create a BodyForce to push the ball forward. The ball has set the touched event active and if it collides with the goalkeeper the ball is caught, so from the server I attached the ball to the goalkeeper.

The problem is from the client game I see the shoot going so fast and while the server process the logic the ball pass through the goalkeeper and goes behind him and studently appears in the goalkeeper hands, so that is a bad experience for the player perspective.

Is there any way to prevent that behavior?

Thinking about that I am wondering if I built the game engine with a wrong approach and maybe I should change how the game works using other techniques that do not show that behavior.

I will appreciate any comment to this problem :grinning:

2 Likes

Can you show us any code by chance?

1 Like

The touched event is unrelaible for fast moving parts, and sometimes doesn’t fire the touched event at all.

To prevent this use a region3 around the ball or raycast to the ball’s next position (You can’t do this since your using bodymovers), so region3 is the best option.

1 Like

Sure,

Player LocalScript:

local function DoShoot(duration)
	shotEvent:FireServer(camera.CFrame.lookVector, duration)
end

Server event manager:

local function OnPlayerShot(player, directionVector, pressDuration)
	local shootForce = Instance.new("BodyForce")
	shootForce.Name = "shootForce"
	local ball = workspace:FindFirstChild("Stadium").Field:WaitForChild("Ball")
	ball:SetNetworkOwner(nil)
	shootForce.Parent = ball
	
	local magnitude = GlobalVariables.SHOT_BASE_MAGNITUDE * pressDuration
	shootForce.Force = directionVector * magnitude + Vector3.new(0, GlobalVariables.SHOT_Y_BASE_MAGNITUDE, 0) 
	
    wait(0.2)
    shotForce:Destroy()
end

Server ball script:

local function BallTouched(otherPart)
	
	local character = otherPart.Parent
	
	if character and not currentCharacter then
		AttachToPlayer(character)
	end
	
end

As far I tested, I agree with you. At this moment I’m thinking to change my game and change my current bodymovers engine (using the game physics) to a Bézier Curves behavior so I will have control to the ball movement and so to the players interaction with the ball.

Alright if you go with beizer curves make it so the ball raycasts to the next position it moves in the equation.

Thank you all of you for the help, I just want to ask you if this could be a good approach to the Bezier soccer ball shoot function. This is the code for passing for example, this is executed from the server:

local function OnPlayerPass(player, playerPassTo)
	
	releaseBallEvent:Fire()
	--time
	local t = 1
	local ball = game.Workspace:FindFirstChild("Stadium").Field:WaitForChild("Ball")
	
    --disable gravity
	local bv = Instance.new("BodyVelocity")
	bv.Velocity = Vector3.new(0,0,0)
	bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
	bv.P = 9000
	bv.Parent = ball
	
    --create the points based on the hearthbeat per seccond
	local fps = t / RunService.Heartbeat:Wait()
	local n = fps
	local p0 = ball.Position
	local p2 =  playerPassTo.HumanoidRootPart.Position
	local p1 = p0 + player.Character.HumanoidRootPart.CFrame.lookVector * ((p2-p0).magnitude / 2) + Vector3.new(0, 20, 0)
	local bezier = Bezier.new(Bezier.quadBezier, n, p0, p1, p2)
	
   --iterate for each point and set the ball position
	for i = 0, n do
		RunService.Heartbeat:Wait()
		local p = bezier:calc(i/fps)
		ball.Position = p
	end
	
	bv:Destroy()
	ball.Position = p2
	
end

Yah it is, assuming there’s only one soccer ball at the same time, if you have multiple soccer balls at the same time consider adding them to a table and updating there positions. (But you porbably only have one soccer ball at a given time)

Make sure to add collision detection with ray-casting.

1 Like