Question, will we also be able to limit how far body parts can stretch or rotate?
Blender has this neat feature where you can set knees to not bend further than X degrees on Y axis.
And you can configure how much a bone is allowed to dislocate/stretch to reach it’s target.
It can make the IK feel more stretchy and flexible (useful for more cartoony/expressive animations)
but can also be used to constrain it so unnatural limb positions and rotations aren’t possible.
You’re way ahead of us Yes, we are working on implementing joint limits that will allow to specify just that, so that shoulders/elbows/… will bend more realistically.
Can you elaborate on what you mean “a bone dislocates/stretches”?
I tried to set up a 3-part rig to mimic a tentacle. Then, I set the root and end and a target. I tried out a few settings but it didn’t work, or in the case of the LookAt mode, didn’t actually bend.
-- StarterCharacterScripts
-- <3 dwifte
local Char = script.Parent
local RunService = game:GetService("RunService")
local LeftIKObj = workspace:FindFirstChild("LeftIK") or Instance.new("Part")
LeftIKObj.CanCollide = false
LeftIKObj.Transparency = 0.8
LeftIKObj.Color = Color3.new(0,0.4,0.8)
LeftIKObj.Size = Vector3.new(0.4,0.4,0.4)
LeftIKObj.Name = "LeftIK"
LeftIKObj.Parent = workspace
local RightIKObj = workspace:FindFirstChild("RightIK") or Instance.new("Part")
RightIKObj.CanCollide = false
RightIKObj.Transparency = 0.8
RightIKObj.Color = Color3.new(0,0.4,0.8)
RightIKObj.Size = Vector3.new(0.4,0.4,0.4)
RightIKObj.Name = "RightIK"
RightIKObj.Parent = workspace
local LeftLegIK = Instance.new("IKControl")
local RightLegIK = Instance.new("IKControl")
LeftLegIK.Name = "LeftLeg"
LeftLegIK.Parent = Char:FindFirstChild("Humanoid")
LeftLegIK.Type = Enum.IKControlType.Position
LeftLegIK.EndEffector = Char:FindFirstChild("LeftFoot")
LeftLegIK.ChainRoot = Char:FindFirstChild("LeftUpperLeg")
LeftLegIK.Weight = 0.5
LeftLegIK.Target = LeftIKObj
RightLegIK.Name = "RightLeg"
RightLegIK.Parent = Char:FindFirstChild("Humanoid")
RightLegIK.Type = Enum.IKControlType.Position
RightLegIK.Weight = 0.5
RightLegIK.EndEffector = Char:FindFirstChild("RightFoot")
RightLegIK.ChainRoot = Char:FindFirstChild("RightUpperLeg")
RightLegIK.Target = RightIKObj
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = {Char,LeftIKObj,RightIKObj,workspace.CurrentCamera} -- workspace camera if you are using a view model
RunService.RenderStepped:Connect(function()
local LeftRay = workspace:Raycast(Vector3.new(Char.LeftFoot.Position.X,Char.LeftFoot.Position.Y+2,Char.LeftFoot.Position.Z),Vector3.new(0,-1,0)*300,params)
if LeftRay then
LeftIKObj.CFrame = CFrame.new(LeftRay.Position,LeftRay.Normal)
end
local RightRay = workspace:Raycast(Vector3.new(Char.RightFoot.Position.X,Char.RightFoot.Position.Y+2,Char.RightFoot.Position.Z),Vector3.new(0,-1,0)*300,params)
if RightRay then
RightIKObj.CFrame = CFrame.new(RightRay.Position,RightRay.Normal)
end
end)
I’m pretty sure its because of your weight property is set too high, so it overwrites animations, for me 0.5 seems to work. If it doesn’t for you, then try and change it until it works.
Basically, when a goal is further away than a arm or leg can stretch, it will dislocate the hips or knees slightly (often small enough to not be super noticeable but is fully customizable) to give it just that extra little bit of stretch/length that it needs to reach it’s target.
This can also happen when a joint reaches it’s rotational limit.
When a joint can’t bend/rotate further as 90 degrees for example, the IK system looks if there is any bone that can be dislocated or slightly pulled out of it’s socket just to give it that tiny extra bit of reach.
This can also prevent jittering in some cases where joint/bone constraints are very tight and limited in movement.
That little bit of stretch/dislocation can give it that tiny bit of extra space that it needs to finish the pose it was trying to get to, but only does so if it absolutely has to.
other than that, if you exaggerate this stretch/dislocate effect, you can make it more cartoony by allowing characters to have spaghetti / rubberhose legs for example.
How are you getting the raw part position without the IK adjustments from the previous Stepped for doing the calculations? Having trouble figuring this out myself, and I don’t want to just follow the Motor6D transforms because that would require searching to find the entire chain. Is there a nice way to do this?
Adding on to @TheNexusAvenger’s report, Motor6D rigs do in fact seem to break the starting position of the IK chain on all types. The chain start appears to teleport towards 0,0,0 but continues to point towards the proper goal, leading to undesirable results.
Seconding this, it looks like stepped is either not after the animation step or the part positions are not updated correctly before stepped is called.
Here is my character in motion with no IK active, the yellow circle is showing the foot’s reported position on stepped and the blue circle is heartbeat.
When using IK, since the position has not been updated, it shows as the previous frame’s modified IK position
Here I would expect the yellow circle to be lower down, next to where the leg should be idling without IK
I still need to work in springs or something to smooth the transitions, but it looks pretty cool like this already. This is likely a very common use case, maybe Roblox can provide some built in easing behaviors.
Some things I definitely wished for though was to be able to offset the endeffector so it can be at the bottom of the foot. Missing this ended up getting confusing at some point for a while while untangling something broken.
I also could not get the pure animated positions without IK influence on Stepped from just the datamodel. I needed to collect the entire motor graph and run the parent-child transform calculations all myself every Stepped to get the pure values.
The code for this is not at all sharable yet though.
Some people above are having trouble with their models. I can probably provide the code for this / a stripped version of the character model tomorrow if needed for comparison. @xtntt@PoptartNoahh
Although I believe my post to be a bug that will get ironed out, I would still love to see how you rigged your model to avoid this issue when you get a chance!
I see, that’s a good suggestion. Currently we force joints to be in the exact same position, but I do see value in providing some type of control that allows you to slightly overreach/stretch. I’ll do some experiments and see how it looks, thanks
This is an issue we are currently working on. The forward kinematics for Motor6D set during the animation step are resolved during the physics step (even though it’s fully kinematic), so currently the only way is to compute FK yourself during stepped, (which is also the solution I’m using for the foot planting above). This is a peculiarity of Motor6D, other kinematic objects like Bone have TransformedWorldCFrame. It’s obviously not ideal so we’re working on adding a simpler way. The two options we’re discussing are
expose something like Motor6D.WorldCFrame : CFrame