I have seen multiple posts 1, 2, and 3 on people wanting to know how recreate Roblox’s IK Control demo.
So I spent 1 hour to make a quick and dirty prototype. Enjoy.
Placefile:
IK Control requires basic setup from hip to foot. This place file should make it convenient to test out the code.
AnimationFootPlant.rbxl (134.0 KB)
Code
local model = script.Parent
--local animationID = "http://www.roblox.com/asset/?id=507777826"
local animationID = "http://www.roblox.com/asset/?id=507767714" --run
local animation = Instance.new("Animation")
animation.AnimationId = animationID
local animator = model.Humanoid.Animator
local walkAnim = animator:LoadAnimation(animation)
walkAnim:AdjustSpeed(0.5)
walkAnim:Play()
--walkAnim:AdjustSpeed(0.25)
local RunService = game:GetService("RunService")
local target = model.HumanoidRootPart.IKTarget1
local IKControl = model.Humanoid.IKControlRightLeg
local chainRoot : Motor6D = IKControl.ChainRoot
local endEffector = IKControl.EndEffector
local RightHip = model:FindFirstChild("RightHip", true)
local RightKnee = model:FindFirstChild("RightKnee", true)
local RightAnkle = model:FindFirstChild("RightAnkle", true)
--motor.part0*c0*transform = motor.Part1*C1
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances= {model}
print(IKControl.SmoothTime)
IKControl.SmoothTime = 0
----motor.part0*c0*transform = motor.Part1*C1
--Solve for Part1
--motor.part0*c0*transform*C1:Inverse() = motor.Part1
--Repeat all the way down to calculate end effector position where it should be without IKControl effecting it
RunService.Stepped:Connect(function(dt)
local rightHipJointWorldCFrame = RightHip.Part0.CFrame*RightHip.C0
local rightkneePart1CF = rightHipJointWorldCFrame*RightHip.Transform*RightHip.C1:Inverse()
local rightFootPart1CF = rightkneePart1CF*RightKnee.C0*RightKnee.Transform*RightKnee.C1:Inverse()
local test = rightFootPart1CF*RightAnkle.C0*RightAnkle.Transform*RightAnkle.C1:Inverse()
local goalTargetWorldCF = test*endEffector.CFrame
local direction = goalTargetWorldCF.Position - rightHipJointWorldCFrame.Position
local raycastResult = workspace:Raycast(rightHipJointWorldCFrame.Position, direction, rayParams)
if raycastResult then
goalTargetWorldCF = goalTargetWorldCF.Rotation + raycastResult.Position
target.WorldCFrame = goalTargetWorldCF
IKControl.Enabled = true
else
IKControl.Enabled = false
end
--target.WorldCFrame = goalTargetWorldCF
end)
--Repeat for Left Leg
local target2 = model.HumanoidRootPart.IKTarget2
local IKControl2 = model.Humanoid.IKControlLeftLeg
local chainRoot : Motor6D = IKControl2.ChainRoot
local endEffector = IKControl2.EndEffector
local LeftHip = model:FindFirstChild("LeftHip", true)
local LeftKnee = model:FindFirstChild("LeftKnee", true)
local LeftAnkle = model:FindFirstChild("LeftAnkle", true)
--motor.part0*c0*transform = motor.Part1*C1
local rayParams = RaycastParams.new()
rayParams.FilterDescendantsInstances= {model}
print(IKControl2.SmoothTime)
IKControl2.SmoothTime = 0
target2.Visible = true
target.Visible = true
RunService.Stepped:Connect(function(dt)
local leftHipJointWorldCFrame = LeftHip.Part0.CFrame*LeftHip.C0
local leftkneePart1CF = leftHipJointWorldCFrame*LeftHip.Transform*LeftHip.C1:Inverse()
local leftFootPart1CF = leftkneePart1CF*LeftKnee.C0*LeftKnee.Transform*LeftKnee.C1:Inverse()
local test = leftFootPart1CF*LeftAnkle.C0*LeftAnkle.Transform*LeftAnkle.C1:Inverse()
local goalTargetWorldCF = test*endEffector.CFrame
local direction = goalTargetWorldCF.Position - leftHipJointWorldCFrame.Position
local raycastResult = workspace:Raycast(leftHipJointWorldCFrame.Position, direction, rayParams)
if raycastResult then
local goalTargetWorldCF = CFrame.new() + raycastResult.Position
target2.WorldCFrame = goalTargetWorldCF
IKControl2.Enabled = true
else
IKControl2.Enabled = false
end
--target.WorldCFrame = goalTargetWorldCF
end)