How can i fix this error?

Hi so i have been working on IK inverse kinematics and i finely got it work i am so happy, But i have this one error that really sucks visually, The legs rotate to the direction they are supposed to but the feet are locked to one rotation? Do you know how i can fix this heres a video:

I know the reason why, Thoso red cubes are the targets, the feet stick to them but they dont rotate to the part so thats why its doing that but i dont know how to fix it

Heres the server script:

local ProceduralModule = require(game:GetService("ReplicatedStorage").ProceduralModule)

local runService = game:GetService("RunService")

local passenger = script.Parent
local root = passenger:FindFirstChild("HumanoidRootPart")
local hum = passenger:FindFirstChild("Humanoid")
local alignOrientation = root:FindFirstChild("AlignOrientation")

local target = workspace:FindFirstChild("Target")

--// IkTargets
local ikTargets = passenger:FindFirstChild("IkTargets")
local left_IkTarget = ikTargets:FindFirstChild("LeftTarget")
local right_IkTarget = ikTargets:FindFirstChild("RightTarget")

--// Raycast parts
local raycastParts = passenger:FindFirstChild("RaycastParts")
local left_RaycastPart = raycastParts:FindFirstChild("LeftRaycast")
local Right_RaycastPart = raycastParts:FindFirstChild("RightRaycast")


--// IKControls
local left_IKControl = hum:FindFirstChild("LeftLegIK")
local right_IKControl = hum:FindFirstChild("RightLegIK")

left_IKControl.Pole = root.LeftAtt
right_IKControl.Pole = root.RightAtt

--// RaycastParams
local rayCastParams = RaycastParams.new()
rayCastParams.FilterDescendantsInstances = {passenger}
rayCastParams.FilterType = Enum.RaycastFilterType.Exclude



coroutine.wrap(function()
	while task.wait(0.25) do
		hum:MoveTo(target.Position)
	end
end)()

runService.Heartbeat:Connect(function()
	local rayCast = workspace:Raycast(root.Position, -1000 * root.CFrame.UpVector, rayCastParams)

	if rayCast then
		local rotateToFloorCFrame = ProceduralModule:getRotationBetween(root.CFrame.UpVector, rayCast.Normal)
		local floorOrientedCFrame = rotateToFloorCFrame * CFrame.new(root.Position)

		local dz = (root.Position.Z - target.Position.Z)
		local dx = (root.Position.X - target.Position.X)
		local horizontalAngle = math.atan2(dx, dz)

		alignOrientation.CFrame = floorOrientedCFrame.Rotation * CFrame.fromOrientation(0, horizontalAngle, 0)
	end
end)

while true do
	ProceduralModule:IkLegStep(left_IkTarget, left_RaycastPart, passenger.PrimaryPart, 1, 2, 1, 0.05, rayCastParams)

	task.wait(0.1)
	ProceduralModule:IkLegStep(right_IkTarget, Right_RaycastPart, passenger.PrimaryPart, 1, 2, 1, 0.05, rayCastParams)

	task.wait(0.1)
end

Heres the module script:

-- Author: Roox4



local ProceduralModule = {}


--// Returns a CFrame rotation between two vectors
--// Credit: @EgoMoose (Roblox)
function ProceduralModule:getRotationBetween(u, v)
	local randomAxis = Vector3.new(1, 0, 0)
	
	local dot = u:Dot(v)
	if (dot > 0.99999) then
		return CFrame.new()
		
	elseif (dot < -0.99999) then
		return CFrame.fromAxisAngle(randomAxis, math.pi)
	end
	
	return CFrame.fromAxisAngle(u:Cross(v), math.acos(dot))
end



--[[

Parameters:

ikTarget ->			A reference to the IK target of a leg
ikRayPart ->		A reference to the raycast part of a leg
root ->				The root part of a model
stepDistance ->		A number that specifies a distance a model has to travel before this function executes
stepForward -> 		A number that specifies a length of a step
stepHeight -> 		A number that specifies a maximum height the leg reaches when stepping
stepWait -> 		A number that specifies a how long the step takes (should be a small value like 0.05)
rayCastParams -> 	A reference to the RaycastParams

--]]


--// Calculates the position of a leg
function ProceduralModule:IkLegStep(ikTarget: BasePart, ikRayPart: BasePart, root: BasePart, stepDistance: number, stepForward: number, stepHeight: number, stepWait: number, rayCastParams: RaycastParams)
	stepWait = stepWait or 0.05
	stepForward = stepForward or 0
	stepHeight = stepHeight or 2
	
	local rayCast = workspace:Raycast(ikRayPart.Position, Vector3.new(0, -1000, 0), rayCastParams)
	
	if rayCast then
		if not ikTarget:GetAttribute("PreviousPos") then
			ikTarget:SetAttribute("PreviousPos", Vector3.new(0, 0, 0))
		end
		
		local previousFootPos = ikTarget:GetAttribute("PreviousPos")
		
		local defaultFootPos = rayCast.Position
		local diff = (defaultFootPos - previousFootPos).Magnitude
		
		--// Do a step
		if diff > stepDistance then
			local finalFootPos = rayCast.Position + root.CFrame.LookVector * stepForward
			local middleFootPos = ((finalFootPos - previousFootPos) * 0.5 + previousFootPos) + Vector3.new(0, stepHeight, 0)
			
			coroutine.wrap(function()
				ikTarget.Position = middleFootPos
				task.wait(stepWait)
				ikTarget.Position = finalFootPos
				
				ikTarget:SetAttribute("PreviousPos", ikTarget.Position)
			end)()
		end
	end
end

return ProceduralModule

So how can i fix this?

1 Like

make the red cubes “look at” the target point, if i remember there is a CFrame function for this.

1 Like

CFrame.lookAt()

2 Likes