IK Foot Planting without using animations

So i’m tryna make footplanting with the IK Controls instance, and I got the part where you plant the foot already.

I know that a way stop the character from straight up sliding around is by playing an animation when walking, and then either adding IK to that or enabling IK when you stop walking. This is not what I’m trying to achieve.

On the unity forums, I found a different method to allow the character to take steps. The idea is that we find the average of the positions of the feet, and then when it is too far away from the character itself, move the feet further away from the character to the front of the character.

I managed to achieve something with this method. However, the effect looks strange. Depending on the maximum distance which I allow the average foot to be from the character itself and the size of the step, the character’s feet for whatever reason had a tendency to be behind or infront the character rather. (As shown in the video)

I assume this has to do with the fact that the way I’m calculating the distance between the average feet and the character and the way I’m finding the position for the raycast for the foot is simplified. However, I don’t really know exactly how I should find these two values in a better way.

Code
local RunService = game:GetService("RunService")

local Char = script.Parent
local Hum : Humanoid = Char:WaitForChild("Humanoid")
local HRP : BasePart = Char:WaitForChild("HumanoidRootPart")

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {Char}
params.IgnoreWater = true
params.RespectCanCollide = true

local MaxFootDist = 3.5

local StepSize = 1.6

local function setup()

	local IkLeft = Instance.new("IKControl")
	local IkRight = Instance.new("IKControl")
	
	local LeftGoal = Instance.new("Attachment", HRP)
	local RightGoal = Instance.new("Attachment", HRP)

	local KneeLeft = Instance.new("HingeConstraint")
	local KneeRight = Instance.new("HingeConstraint")
	
	KneeLeft.Attachment0 = Char.LeftLowerLeg.LeftKneeRigAttachment
	KneeLeft.Attachment1 = Char.LeftUpperLeg.LeftKneeRigAttachment
	KneeRight.Attachment0 = Char.RightLowerLeg.RightKneeRigAttachment
	KneeRight.Attachment1 = Char.RightUpperLeg.RightKneeRigAttachment

	KneeLeft.Parent, KneeRight.Parent = HRP, HRP
	
	IkLeft.ChainRoot = Char.LeftUpperLeg
	IkLeft.EndEffector = Char.LeftFoot
	IkRight.ChainRoot = Char.RightUpperLeg
	IkRight.EndEffector = Char.RightFoot
	
	IkLeft.Target = LeftGoal
	IkRight.Target = RightGoal
	
	IkLeft.Weight = 1
	IkRight.Weight = 1
	
	IkLeft.Parent, IkRight.Parent = Hum, Hum
	
	local Left: CFrame, Right: CFrame = Char.LeftFoot.LeftFootAttachment.WorldCFrame, Char.RightFoot.RightFootAttachment.WorldCFrame


	
	local Conn = RunService.RenderStepped:Connect(function()
		
		local AverageFoot = (Left.Position + Right.Position)/2
				
		if (AverageFoot - (HRP.Position)).Magnitude > MaxFootDist then
			local LDist, RDist = (Left.Position - HRP.Position).Magnitude, (Right.Position - HRP.Position).Magnitude
			if LDist > RDist then
				--Step Left Foot
				local ray = workspace:Raycast(Char.LowerTorso.LeftHipRigAttachment.WorldCFrame.Position + StepSize * HRP.CFrame.LookVector, Vector3.new(0, -2* Hum.HipHeight, 0), params)
				if ray then
					print(1)
					Left = CFrame.fromMatrix(ray.Position, -ray.Normal:Cross(HRP.CFrame.LookVector), ray.Normal)
				else
					ray = workspace:Raycast(Char.LowerTorso.LeftHipRigAttachment.WorldCFrame.Position, Vector3.new(0, -2 * Hum.HipHeight, 0), params)
					if ray then
						print(2)
						Left = CFrame.fromMatrix(ray.Position, -ray.Normal:Cross(HRP.CFrame.LookVector), ray.Normal)
					else
						print(3)
						Left = CFrame.fromMatrix(Char.LowerTorso.LeftHipRigAttachment.WorldCFrame.Position + Vector3.new(0, -Hum.HipHeight, 0), -Vector3.yAxis:Cross(HRP.CFrame.LookVector), Vector3.yAxis)
					end
				end
			else
				--Step Right Foot
				local ray = workspace:Raycast(Char.LowerTorso.RightHipRigAttachment.WorldCFrame.Position + StepSize * HRP.CFrame.LookVector, Vector3.new(0, -2 * Hum.HipHeight, 0), params)
				if ray then
					Right = CFrame.fromMatrix(ray.Position, -ray.Normal:Cross(HRP.CFrame.LookVector), ray.Normal)
				else
					ray = workspace:Raycast(Char.LowerTorso.RightHipRigAttachment.WorldCFrame.Position, Vector3.new(0, -2 * Hum.HipHeight, 0), params)
					if ray then
						Right = CFrame.fromMatrix(ray.Position, -ray.Normal:Cross(HRP.CFrame.LookVector), ray.Normal)
					else
						Right = CFrame.fromMatrix(Char.LowerTorso.RightHipRigAttachment.WorldCFrame.Position + Vector3.new(0, -Hum.HipHeight, 0), -Vector3.yAxis:Cross(HRP.CFrame.LookVector), Vector3.yAxis)
					end
				end
			end 
		end
		
		LeftGoal.WorldCFrame, RightGoal.WorldCFrame = Left, Right
	end)
end

setup()

(I am sure that the footplanting itself is fine, the raycasting and the calculations I do to determine the position of the place the foot lands absolutely works)

Edit: The video is a bit laggy, I can provide another video and show the character at another angle if needed

1 Like