How to deal with the limitations of the FABRIK algorithm for procedural animation

For my game, I plan to use procedural animation similar to the steps shown below in the video.

Moreover, for step 2 in the video to fix my mech’s leg on the ground (represented by the possible position of the red dot in my gif below) by using a constant iteration of the FABRIK algorithm. It seems to work fine until the AAAAAAAAA moment where the target position gets too close for the constraints and algorithm combined to handle.

Now I can’t think of any other way to handle this issue via code and changes to the algorithm itself though you may try since its open source. Most probably it’s likely to do with the hinge constraint being really strict and messing with how the algorithm functions:

This specific piece of code in the hinge constraint

GitHub link

--Debug the angle to adjust your own Rig
    --print(math.deg(angleAdjust))
    --Issue: It looks pretty buggy if continuosly iterated
    --Checks for elevation or depression
    if angleAdjust < self.AngleOfDepression then

        --Get the rotation Axis
        local rotationAxis = newDir:Cross(self.CenterAxis)

        --Very strict and doesn't fit the iteration
        --Get Cframe and rotate it to max possible angle
        local refCF = self.Part.CFrame*CFrame.fromAxisAngle(rotationAxis,-self.AngleOfDepression)
        
        --Rotate it anti clockwise from parts right vector method
        --local refCF = CFrame.new(Vector3.new(),newDir)*CFrame.fromAxisAngle(rotationAxis,math.rad(1))

        return refCF.LookVector.Unit*limbLength

    elseif angleAdjust>self.AngleOfElevation then
        
        --Get the rotation Axis
        local rotationAxis = newDir:Cross(self.CenterAxis)

        --Very strict and doesn't fit the iteration method
        --Get Cframe and rotate it to max possible angle
        local refCF = self.Part.CFrame*CFrame.fromAxisAngle(rotationAxis,self.AngleOfElevation)
        
        --Rotate it clockwise from parts right vector view
        --local refCF = CFrame.new(Vector3.new(),newDir)*CFrame.fromAxisAngle(rotationAxis,-math.rad(1))

        return refCF.LookVector.Unit*limbLength 

    end

Now I’m wondering if there is any other short term way to solve this issue in my game.

Currently, I’m thinking of:

  • Detecting if the target point is near and just using predefined animations
    (If so I would like some pointers on how to do it)

  • Clever map design and a simple collision box to avoid this issue

  • Maybe moving the hip up to distance the target point away from the AAAAAAAAA moment

What are your thoughts and ideas to best tackle with this issue?

you could just move the target IK point further away if it gets too close, not a good solution but hopefully a working one

1 Like

Yeah, that works and in fact, it has helped me think of a new idea after some experimenting, I found out that it’s the constraints that cause the algorithm to freak out like telling it to divide by 0 trying finding to find a solution where the leg can’t possibly reach.

I guess my solution will be to change constraints to be more allowing when the target points get close so it doesn’t freak out and still looks a bit decent.

1 Like