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?