Touch Soccer Issues

I am currently attempting to script a soccerball that will kick whenever it is touched. I have the basic foundation of the ball completed, however I am still running into issues such as…

1.) The roll is stopping too abruptly, I would like to see the roll extended
2.) The gravity on the ball (I’m assuming which) is too strong, I would like to see the ball be slower while in the air --WITHOUT CHANGING THE GRAVITY OF PLAYER

Another thing I am trying to figure out is how I can add power checkers so that whenever you are kicking on the other side of the field, you will have the power to make it close to the goal instead of having the flat max power all across the field

Any advice would be appreciated, thank you!

local soccerBall = script.Parent
--local players = game:GetService('Players')
local debris = game:GetService("Debris")

local lastTouched = {}
local debounce = .4

local lowP = 32 --Minimum Power
local highP = 52 --Maximum Power
local verticalPower = highP

local power = 80

local applyFriction = false
local rotationalForce = 42

local function createBAV()
	if(soccerBall.AssemblyAngularVelocity.Magnitude > 0 and soccerBall:FindFirstChild("BodyAngularVelocity") == nil) then
		spawn(function()
			applyFriction = true
			local bav = Instance.new("BodyAngularVelocity")
			bav.Parent = soccerBall
			bav.AngularVelocity = Vector3.new(0,0,0)
			bav.P = 10
			bav.MaxTorque = Vector3.new(rotationalForce, rotationalForce, rotationalForce)
			while applyFriction and soccerBall.AssemblyLinearVelocity.Magnitude > 0 do
				task.wait()
			end
			applyFriction = false
			bav:Destroy()
		end)
	end
end

local function ballPhysics(otherPart)
	if(otherPart.Name == "FrictionPart" and applyFriction == false) or (otherPart.Parent == "MainField" or otherPart.Name == "OOB" and applyFriction == false)then
		createBAV()
	end
end

soccerBall.Touched:Connect(ballPhysics)

local function newForce(soccerBallPosition, vector)
	local distanceNum = 62
	local verticalPower = highP
	local distanceCheckPartFolder = game.Workspace.soccerField.DistanceCheckFolder
	local goalFlag = soccerBall.Position.X > 0 -- true = Red Goal. false = Blue Goal
	local goal
	
	if(goalFlag) then
		goal = distanceCheckPartFolder.DistanceCheckPartsRedGoal
	else
		goal = distanceCheckPartFolder.DistanceCheckPartsBlueGoal
	end
	
	if(math.abs(soccerBallPosition.X) < math.abs(goal.GoalCenter.Position.X)) then
		local zVal = (goal.GoalCenter.Position.X - soccerBallPosition.X) * vector.Z/vector.X + soccerBall.Position.Z
		if (zVal < goal.DistanceCheckPart1.Position.Z and zVal > goal.DistanceCheckPart2.Position.Z) then
			local distanceFromGoal = (Vector2.new(soccerBallPosition.X, soccerBallPosition.Z) - Vector2.new(goal.GoalCenter.Position.X, zVal)).Magnitude		
			if (distanceFromGoal < distanceNum) then
				local newVP = verticalPower * (distanceFromGoal/distanceNum)
				verticalPower = newVP
			end
		end
	end
	if(verticalPower < lowP) then
		return lowP
	elseif(verticalPower > highP) then
		return highP
	else
		return verticalPower
	end
end

local function ballKicked(player, character, walkspeed, lookVector)--, moveDirectionVector)
	if character:FindFirstChildWhichIsA("Humanoid") and not table.find(lastTouched, player) then
		
		local playerHRP = character.HumanoidRootPart
		local force
		local verticalForce = verticalPower
		local powerForce = power
		
		local lookV = lookVector
		--local directionV = moveDirectionVector
		
		if(walkspeed == 22) then
			verticalForce = 4
			powerForce = 40
		elseif(walkspeed == 24) then
			--if(moveDirectionVector.Magnitude == 0 and soccerBall.Position.X * lookV.X > 0) then
			--	verticalForce = newForce(soccerBall.Position, lookV)
			--elseif(soccerBall.Position.X * directionV.X > 0) then
			--	verticalForce = newForce(soccerBall.Position, directionV)
			--end
			if(soccerBall.Position.X * lookV.X > 0) then
				verticalForce = newForce(soccerBall.Position, lookV)
			end
		end
		
		--if(moveDirectionVector.Magnitude == 0) then
			force = Vector3.new(powerForce*lookV.X, verticalForce, powerForce*lookV.Z)
		--else
		--	force = Vector3.new(powerForce*directionV.X, verticalForce, powerForce*directionV.Z)
		--end
		

		local BV = Instance.new("BodyVelocity")
		BV.Parent =  soccerBall
		BV.maxForce = Vector3.new(1, 1, 1) * math.huge
		BV.P = 5000
		BV.Velocity = force
		debris:AddItem(BV, .2)
		
		if(walkspeed == 24)  then
			applyFriction = false
		end

		table.insert(lastTouched, player)
		delay(debounce, function()
			local Position = table.find(lastTouched, player)
			if not Position then
				return
			end
			table.remove(lastTouched, Position)
		end)
	end
end

soccerBall.KickEvent.OnServerEvent:Connect(ballKicked)
2 Likes

You can change the CustomPhysicalProperties of the ball. Lowering the Friction will make it “roll” for longer, and lowering it’s Density will make it go higher when you kick the ball.

2 Likes

Thank you! Solution to the height and rolling issue, still finding a solution to make the ball go slower…

For the gravity issue you can apply a VectorForce in the ball that always pushes upward. Don’t go too high or the ball will float off the ground.
You can calculate the force applied to the ball with a formula that takes a percentage of the field available and reduces the force by that percentage. Of course you can make it be 100% from your goal to center field and reduce it for the rest of the length of the field down to about 50% (for example) so that the ball still has some force to make goal kicks.

2 Likes

Add a VectorForce and an Attachment in the ball, then set the force location to center of mass and the attachment to the one you put in the ball. Then set the force to (0, 1000, 0)

Video demo below:

2 Likes

Thank you so much!!! I really appreciate this friend…

In regards to the VectorForce, would this line be contained in the original code or would it be within the attachment of the soccerBall?

You can do it either way. Whatever works best for you.

1 Like