CCDIKController - Alternate inverse kinematics method for Motor6D rigs

Yeah. Here’s some unity code you can translate into studio code to get you started.


From this video

Stepping horizontally would be similar except on a different axis.
For world space to object space, you can take the CFrame and do :ToObjectSpace

9 Likes

Thank you so much for taking time out your day to help me.

I am going to work out how to covert this into LUA luckily I have had experience with C#.

2 Likes

Hello! This module is just Awesome! But sadly the Github Page is missing :frowning:
And so I’ve got 0 idea on how to use this module, it’d be great help if you could fix it, or maybe add a tutorial here!

Thanks anyways for the module!

2 Likes

Theirs documentation and a tutorial in the 3rd post.

2 Likes

Update!

After I was contacted by someone who wanted a version which could be compatible with animations I have decided to officially push a version which fixes the error.

Before:

After:
Notice how the idle animations are moving the IK effected limb:

The only difference is that for it to work the iteration should be done within .Stepped.

--Stepped for the CCDIK to reset the .Transform property
RunService.Stepped:Connect(function()
    local goal = leftTarget.Position
    leftLegController:CCDIKIterateOnce(goal,0) --0 tolerance always try to iterate towards goal
end)

The explanation on how it works is that it will:

  1. Apply the .Transform animations onto the C0 instead

  2. Perform the usual move limb closer towards the goal

  3. Then apply constraints

In the proper order instead of:

  1. Perform the usual move limb closer towards the goal

  2. Then apply constraints

  3. Then animations are applied moving them out of the constraint range

CCDIK iterate step function fixed
function CCDIKController:_CCDIKIterateStep(goalPosition, step)
	local constraints = self.Constraints
	local useLastMotor = self.UseLastMotor and 1 or 0 --Makes it so that it iterates the only one motor in the table
	for i = #self.Motor6DTable - 1 + useLastMotor, 1, -1 do
		local currentJoint = self.Motor6DTable[i]

		currentJoint.C0 *= currentJoint.Transform -- apply animations to C0
		self:RotateFromEffectorToGoal(currentJoint, goalPosition, step)

		currentJoint.Transform = CFNEW()

		if constraints then
			local jointConstraintInfo = constraints[currentJoint]
			if jointConstraintInfo then
				if jointConstraintInfo.ConstraintType == "Hinge" then
					self:RotateToHingeAxis(currentJoint, jointConstraintInfo)
				end
				if jointConstraintInfo.ConstraintType == "BallSocketConstraint" then
					self:RotateToBallSocketConstraintAxis(currentJoint, jointConstraintInfo)
				end
			end
		end
	end
end
9 Likes

Fantastic stuff here. Great work!

1 Like

Is there a way to fix this issue with the arms

local leftupperArm = dummyMotor6Ds["LeftShoulder"]
local leftelbow = dummyMotor6Ds["LeftElbow"]
local lefthand = dummyMotor6Ds["LeftWrist"]

local rightupperArm = dummyMotor6Ds["RightShoulder"]
local rightelbow = dummyMotor6Ds["RightElbow"]
local righthand = dummyMotor6Ds["RightWrist"]
local leftArm = {leftupperArm,leftelbow,lefthand}
local rightArm = {rightupperArm,rightelbow,righthand}

local leftarmController = CCDIKController.new(leftArm)
local righrarmController = CCDIKController.new(rightArm)

RunService.Heartbeat:Connect(function()
local goal = workspace.Steer.CFrame * Vector3.new(0, 0.1, -(workspace.Steer.Size.Z * 0.5 - 0.2))
local goalr = workspace.Steer.CFrame * Vector3.new(0, 0.1, (workspace.Steer.Size.Z * 0.5 - 0.2))
leftarmController:CCDIKIterateOnce(goal, 0)
righrarmController:CCDIKIterateOnce(goalr, 0)
end)
3 Likes

Add constraints to make the arms bend the right way by using the :GetConstraints() function. Remember to create the Constraint Instances and attachment like the example in the test place.

5 Likes

So I’m back again unfortunately, so the IK legs make the mech rotate into another direction when its idle. Is this something to do with my code? I may have converted some of the C# into LUA incorrectly. I use a heartbeat script to update the IK legs every second. If this isnt enough information i can give you more. Sorry if this is asking for to much.

1 Like

I’m honestly not sure, but here’s some ideas to debug with

  • What’s the front face of the legs and the mech? Are they all facing the same direction?

If this is not the issue, then I would want to know what “idle” means. I doubt it’s your code causing the bug, but rather the default behavior of the module

3 Likes

I am going to supply a video to show what I mean by “idle” also the legs and mech are facing the correct position. Hopefully you can help me work out a solution lol.

robloxapp-20210727-2235310.wmv (3.1 MB)

2 Likes

I might try ditch the idea of IK and just use normal animations since im to dumb to work this out lol. Or i might try rework the code with my own ideas lol. I’m just really confused on how to get this working. I might try maybe allowing for a normal humanoid rig to be able to work in IK then use that logic for a mech?

1 Like

Hi, it’s been a heck of a few days, and I missed your responses. I would recommend first fixing the leg issue where it lags behind the torso.image
To fix this, you’re gonna make sure that your raycast is from the torso down. When the legs step forward, then they should be directly under where the torso was when they started stepping forward. You might have to lower the walkspeed for this.
You might find the rotating fixed. I think the physics were messing with it. I would heavily recommend to anchor all parts and not use a humanoid.

4 Likes

Thanks sorry for being so needy lol. Ill give you another response saying if it worked or not. thanks :slight_smile:

1 Like

Oh yeah no problem at all. This is really interesting and I’ll soon be attempting an ik solver with @alexfinger21

3 Likes

Have fun with that and thanks for all the help. Hopefully your solution works!

3 Likes

Aight so unfortunately i still have 2 issues. 1 is that the rotation still exists. But this may be caused by the humanoid. Unfortunately im using Humanoid:Move to move the mech. How would i remove the humanoid. Is their an alternative to Humanoid:Move that doesnt use humanoid? Ill be patient this time lol.

1 Like

Removing humanoid is actually gonna make your life easier in the long run. WASD each stands for a vector that the position offseted by. For simplicity’s sake, assume forward is the player’s torso.CFrame.Lookvector. Every frame you’re gonna:

  1. If W is pressed then
  2. Raycast to Torso.Position+Torso.CFrame.LookVector * Velocity * Deltatime from the center of the mech
  3. If the raycast hit something then don’t move (collision)
  4. Otherwise move the mech to that position and calculate IK for the legs

Once you get that and it’s bug free, you would use the same process for moving backwards, and a body gyro for A and D (the mech rotates). Alternatively, you can have a camera lock and rotate the mech that way (A and D would now move the mech sideways). If you can think it, you can probably code it.

3 Likes

I apologise for my lack of understanding but why would I need to raycast to see if it collides? Cant I enable can collide? Also for moving the mech itself forwards/backwards would I use a bodyVelocity. Also im gonna attempt to use the camera lock for the sake of future pvp. Also if i removed the humanoid it’d also need a way for it to stand up. Humanoid allows it to standup. But if i remove the humanoid it’ll just fall down.Sorry for so many questions but i appreciate the amount of effort and care you put into these answers. Stay pro :slight_smile:

1 Like

why am i getting 404 when i try click the API and set up?

1 Like