Hello there, I’m @dthecoolest and this is my first open-source project which I made to contribute back to the community.
Credit
One of the main reason this project is open-source, couldn’t have done it without them:
@EgoMoose The basis: FABRIK Algorithm explanation video and also for the RotatedRegion3 Module for primary and secondary constraints.
@TeamSwordphin Experimental IK Creature: inspiration to use the FABRIK method
@LMH_Hutch and @iGottic example projects for IK Motor6d Manipulation
@Kironte OOP Libary to implement OOP simplification and methods
@Arch_Mage RigEdit lite 100% helped me understand and visualize Motor6ds
Showcase
Version 1.2 , Added lerping to motors, 100% makes it look a lot smoother even in the glitchy areas.
https://i.imgur.com/pNGisc3.mp4
Version 1.1, Improved the foot placement system, rough around corners but it’ll do:
https://i.imgur.com/pELmHt7.mp4
This is done by the below code:
Code to implement foot placement system
--Foot placement system
local footParams = RaycastParams.new()
footParams.CollisionGroup = "MovementSys"
leftLegChain.FootPlacementRaycastParams = footParams
leftLegChain.LengthToFloor = 20
--Get all the attachments in the left foot
leftLegChain.FootBottomAttachment = lowerBody.LeftLeg.LFeet.FootBottom
leftLegChain.FootBottomRightAttachment = lowerBody.LeftLeg.LFeet.FootBottomRight
Version 1.0, Primary and Secondary constraints! this will help tell the algorithm to try not to calculate the impossible by making the secondary constraints less strict.
https://i.imgur.com/bD3qcm7.mp4
Without secondary constraints:
The leg goes sicko mode
Version 0.9, Multiple limbs support including the spine/torso, +R15 support
Watch them all vibe
https://i.imgur.com/Smq2A0S.mp4
Old Versions Showcase and the features they introduced
Version 0.8, Iterate until the goal, and swapped parameters
(bugged with constraints)
(Fixed in version 1.0, now it update motors and hence updates the constraint parts as well)
leftLegChain:IterateOnce(goalPosition,toleranceInStuds)
leftLegChain:IterateUntilGoal(goalPosition,toleranceInStuds,maxIterationUntilBreakCount)
https://i.imgur.com/1Ct1NS6.mp4
Version 0.7, Now featuring Constraints! :
https://i.imgur.com/QWFD2C8.mp4
Unconstrained version:
Assets
Download the latest release place file with the code in my Github
(Download the zip file of the latest release version )
v1.3 where I consolidated it into a single module script for easy installation.
The IK Solver only module.
(Not recommended as it doesn’t include all the objects and features of the system)
(Can be good to study how I Implemented the FABRIK algorithm)
Introduction
While there are many inverse kinematics tutorials and resources on Roblox the ones I found use relatively complex trigonometry methods intended for use for R15 characters. While they helped me understand how motor6d’s work I believe the trigonometry math will get more complex for my purpose of making a mech game where mech legs often have more than 2 joints and 2 limbs cuz thats what makes mech’s look cool and functional.
Further searching led to this amazing project by @TeamSwordphin using the FABRIK algorithm showing the possibilities of the algorithm with the downside that it doesn’t work for motor6d rigs and the code has been automatically generating the limbs making it hard to edit for new scripters like me.
Consequently, I created this resource to share my findings and hopefully gain the benefits of open-sourcing a project especially code review. Also, I aim to learn how GitHub works via this project.
How it works
Open if you are interested
The algorithm uses the FABRIK algorithm seen below in EgoMoose’s video which greatly helped me out.
EgoMoose's FABRIK explanation Video
However, to translate the FABRIK algorithm into Roblox’s Motor6D rigs I found out I could just obtain the vector from joint to joint via c0 and c1 manipulation seen in the thread below via this function:
--find length of the joints
local function lenOneToTwo(partOne,partTwo)
--Check if its a motor6d
if partOne:IsA("Motor6D") and partTwo:IsA("Motor6D") then
local vecOne = partOne.C1.p
local vecTwo = partTwo.C0.p
local combinedVector = vecTwo-vecOne
return combinedVector
end
return "Error: motor 6ds are not inserted in the function"
end
Transforming positional points to Motor6D joints - #2 by dthecoolest
Usage, Instructions, and Explanation
- Disclaimer: This IK method uses an odd CFrame method that causes problems if your model is not oriented (0,0,0) and not all your parts are facing front like the R15/R6 dummy. To solve this view the newer CCDIK method which doesn’t have this issue:
The instructions for using the system have been transferred to the GitHub wiki below:
It’s incomplete so if you have a question please reply in the thread
--[[
This is the LimbChain class which manages the Motor6Ds within a rig using the FabrikSolver class to do inverse kinematics with.
API:
Constructors:
LimbChain.new(Table Motor6DTable, Bool includeFoot, Bool spineMotor)
> Creates the inverse kinematics handler for a set of Motor6D's inserted in the table
>Motor6ds are conected sequentially in increasing order from the origin towards the endpoint
>Motor1, Motor2, Motor3
>UpperLeg, LowerLeg, Foot for R15, makesure these motors are like a tree branch
> Spine motor is an odd workaround don't use it, please only works for Mr floop man
Methods:
LimbChain:IterateOnce(Vector3 targetPosition, Number tolerance)
> Performs one forwards or backwards iteration of the fabrik iteration on the IteratedLimbVectorTable
> Tolerance indicates the distance when the iterations stop if the goal is already reached
LimbChain:IterateUntilGoal(Vector3 targetPosition, Number tolerance, Number breakcount)
> Performs forwards or backwards iteration of the fabrik iteration on the IteratedLimbVectorTable
> Until goal is reached (including tolerance) or maximum iterations in breakcount is reached
LimbChain:UpdateMotors()
> Rotates the Motor6D's until the they match the directions of the curent IteratedLimbVectorTable vectors
LimbChain:DebugModeOn(Bool freezeLimbs, Bool primaryDebug,Bool secondaryDebug)
> Turns on the debug mode for the FabrikSolver, primary and secondary constraints depending on the bool.
> the freeze limbs will tell the fabriksolver to not perform iteration and instead update the constraints debug
> Essentially freezing them in place so you can change the orientation of the constraints
Properties:
LimbChain.LerpMotors
> Bool that enables or disables the lerp methods for the IK
LimbChain.LerpAlpha
> Number that represents the alpha in CFrame:Lerp() from the motors current C0 towards the IK target goal CFrame
LimbChain.IncludeFoot
> Bool that enables or disables the foot placement method which rotated the foot independently
LimbChain.FootBottomAttachment
> Attachment required for the foot placement system
LimbChain.FootBottomRightAttachment
> Attachment required for the foot placement system place to the right of the initial footbottom
LimbChain.FootPlacementRaycastParams
> The raycast params object for the foot to detect the floor
LimbChain.DebugMode
> Bool to turn on debug mode which visualizes the limb vectors and the constraints
> Currently does nothing as this object has debugging properties turned off
LimbChain.FootBottomAttachment
> Attachment required for the foot placement system
LimbChain.PrimaryLimbConstraintTable
> Table of FabrikConstraint objects which do the constraining for each limb
LimbChain.SecondaryLimbConstraintTable
> Table of FabrikConstraint objects which do the constraining for each limb if the target position is
> out of the primary constraint region
LimbChain.PrimaryConstraintRegionFromParts
> Table of BaseParts that the primary constraint region will activate in accordance to the TargetPosition
Enjoy!
- dthecoolest
Thanks EgoMoose for the FABRIK explanation and the explanation on how to do constraints.
--]]
For further exploration, I recommend downloading the place file I use for testing in my GitHub called “MechTest.rbxlx” and play around with it by dragging the LTarget.
Attribution and Credit
If you do use any of the resources provided within a game please credit me in the description or an in-game credits screen. Otherwise, the project uses an MIT License.
Edit: Disclaimer for the mech legs model included in the project file which demonstrates the constraints mechanism.
Yeah to be honest I made it in the image of the Touro from Brigador which is a mech game that rekindled my interest in making mech games on Roblox and started my scripting journey.
Brigador Touro Speen gif
Luckily and wisely I emailed the developers to confirm permissions and they have been really supportive of my project, and the good news is that it should be fine if it’s free for the community.
But yeah don’t try to monetize and use it in a real game due to how the American copyright law works and how the devs are working hard on a new Brigador game. The blocky industrial design of the current legs is way too similar I suggest just making something totally original for the best.
I will try making my own mech designs like I once did with Roblox games like build your mech/cybersuit and Plane Crazy by @rickje139 and @madattak but sadly I have less time than I once did before.
In the meanwhile please support the Brigador devs by buying Brigador in you are interested in the retro game genre, but be aware the game has quite some mature themes as it deals with war themes like most works in the mech genre.
The Future of the Project
As of 19 January 2021 this project is deprecated in favor of my new IK method CCDIK.
The reason being this newer module is better scripted and doesn’t have the (0,0,0) orientation requirement of the current method. Moreover, it’s easier to set the constraints using a dictionary and attachments rather than welding the parts onto the model than creating objects for it. Currently, planning to create one massive IKController with both FABRIK and CCDIK combined stay tuned I guess.
Past Project Goals: 4 September 2020
The constraint method is done and the OOP has been implemented however:
-
The math for using constraints can get intensive increasing script activity from 3% to 10%. Moreover, setting the axis of the conical constraint can get pretty complicated so I’m searching for a better method.
-
Using OOP code to execute the methods has been simplified but could use more functionality and methods for stuff like debugging the position of the joints.
-
Maybe even functionality for multiple targets
-
Better control of how many iterations to perform to reach the target goal maybe?
Past Project Goals: Aug 26, 2020
Currently, the IK Solver is “functional” but complicated to use so I’m planning to make it more accessible similar to the fast cast module via OOP methods which I’m severely lacking in skill to do having just finished the PeasFactory advanced tutorials on youtube.
However, before that I’m trying to work out the conical constraint method as described by EgoMoose in order to further flesh out the functionality for my own game.
Thanks for reading. Please message me if someone has made a giant enemy spider with inverse kinematics or have used this project.