Final IK

It has a target but not an aim transform. It has both and works correctly with weapons though (at least it does with the pistol I tested).
 
Hi I followed the steps from the Final IK integration guide lines: https://opsive.com/support/documentation/ultimate-character-controller/integrations/final-ik/ but I am having an issue with the interaction system.

It says that simply by adding the interaction system to the character and an interaction object to the interactable it should work. But when I interact with my button it moves the platform but the IK interaction does not happen.

Looking at the code I realised that I was suppose to add a Ability IK Target to the interactable. It is probably a good idea to add that in the docs, because I heard of other people saying they couldn't get it to work. I mean it sounds obvious now but for people who never used IK before it might not be.

I am also getting an error once the ability finishes. I think you are missing a "return" somewhere.

This is your code:

C#:
public override void SetAbilityIKTarget(Transform target, IKGoal ikGoal, float duration)
        {
            if (m_InteractionSystem == null) {
                Debug.LogError("Error: The character must have the Interaction System component in order for the ability to set an IK target.");
                return;
            }

            if (target == null) {
                m_InteractionSystem.PauseInteraction(IKGoalToEffector(ikGoal));
            }

            var interactionObject = target.gameObject.GetCachedComponent<InteractionObject>();
            if (interactionObject == null) {
                Debug.LogError("Error: The target " + target.name + " must have the FinalIK Interaction Object attached.");
                return;
            }

            m_InteractionSystem.StartInteraction(IKGoalToEffector(ikGoal), interactionObject, false);
        }
When the target is null then calling target.gameObject will return an error. I am not sure what you should do to fix this the correct way. My guess is add a return statement if target is null.

I added the return in your source code and it seems to work wothout any problems now
 
I spoke too soon, I get a weird behavior if I interact again while the animation is playing. The character starts pressing in the look direction. No idea how I would fix this except make the interact ability not start until it has finished. But I don't know how to do that either.
 
Last edited:

Justin

Administrator
Staff member
You're right - it needs a return and I'll add a note about the Ability IK Target.

I get a weird behavior if I interact again while the animation is playing.
So you are interacting, and then you try to interact again while the current interact ability is active? The interact ability isn't concurrent so it shouldn't be able to start a second time.
 
I believe I found the cause of all the problems I had making the IK interaction.

First of all the interaction should stop and not pause when the target is null. So I changed this functions in the Final IK bridge component.

C#:
public override void SetAbilityIKTarget(Transform target, IKGoal ikGoal, float duration)
        {
            if (m_InteractionSystem == null) {
                Debug.LogError("Error: The character must have the Interaction System component in order for the ability to set an IK target.");
                return;
            }

            if (target == null) {
                m_InteractionSystem.StopInteraction(IKGoalToEffector(ikGoal));
                //m_InteractionSystem.PauseInteraction(IKGoalToEffector(ikGoal));
                return;
            }

            var interactionObject = target.gameObject.GetCachedComponent<InteractionObject>();
            if (interactionObject == null) {
                Debug.LogError("Error: The target " + target.name + " must have the FinalIK Interaction Object attached.");
                return;
            }

            m_InteractionSystem.StartInteraction(IKGoalToEffector(ikGoal), interactionObject, false);
        }
Then the on the Ability IK Target component (attached to the interactable object), you have to make sure its "duration" is just above (Lower or equal won't work) the Interaction Object component (by Final IK) duration (controlled by the "Weight Curves" max length).

The next issue is with the interaction OnAnimatorInteractionComplete Event. The interaction ability can stop while the IK Interaction still hasn't finished. This means the ability can start again even though the IK interaction hasn't completed which result in weird behaviors. Instead of using the animator event to complete the ability you can use the duration of the interaction (as long as the duration is the same for all interaction that's fine, otherwise just add another interaction ability to your character and assign it a different ID).

I think the only way to fix the duration disparity between Interact Ability / Ability IK Target / Interaction Object would be to change the code even more... not sure if it is worth it though since you can deal with it just by being careful.

I hope that helps.
 
Actually, I hadn't realised before because the interaction was so fast. There is definitely some jitter. Especially in the head of the character. Which makes me think that the look At IK and interaction system are fighting each other to move the character IK. Maybe they are updated at the same time?
I'll need some free time to look into it in more detail, if anyone fins the cause please let us know here.
 
I think I found the cause of the Jitter!

The Interaction system updates the look At during Update, not sure why:

C#:
void Update() {
            if (fullBody == null) return;
            
            UpdateTriggerEventBroadcasting();
            
            Raycasting();
            
            // Finding the triggers in contact and in range
            triggersInRange.Clear();
            bestRangeIndexes.Clear();

            for (int i = 0; i < inContact.Count; i++) {
                int bestRangeIndex = -1;

                if (inContact[i] != null && inContact[i].gameObject.activeInHierarchy && inContact[i].enabled && ContactIsInRange(i, out bestRangeIndex)) {
                    triggersInRange.Add(inContact[i]);
                    bestRangeIndexes.Add(bestRangeIndex);
                }
            }

            // Update LookAt
            lookAt.Update();
        }
This clashes with Final IK bridge the wants Look At to be only updated in Fixed update.

So how do we fix this?

The easy solution is to comment out the "lookAt.Update();" line but if possible I do not want to change the Final IK source code. Be aware that if you did that then the "Look At Target" on the Interaction Object won't work anymore.

Solution two would have been to disable the Interaction System component and copy the content of the Update function from InteractionSystem to Final IK bridge. The problem is that some methods in Update are private, so due to restriction levels, that is not possible.

Solution 3 contact the devs at RootMotion and ask them for guidance.

@Justin if you come up with other ideas do let me know
 

Justin

Administrator
Staff member
The next issue is with the interaction OnAnimatorInteractionComplete Event. The interaction ability can stop while the IK Interaction still hasn't finished. This means the ability can start again even though the IK interaction hasn't completed which result in weird behaviors. Instead of using the animator event to complete the ability you can use the duration of the interaction (as long as the duration is the same for all interaction that's fine, otherwise just add another interaction ability to your character and assign it a different ID).
That's a good catch. In the interact ability I'll track the scheduled event for disabling the target and if the interact has been completed before the ik duration then it'll stop the interaction early.

This clashes with Final IK bridge the wants Look At to be only updated in Fixed update.
Interesting. I think contacting RootMotion is a good option to see why that is the case, but maybe there is a way to check if the FinalIK interaction component is active and if it is then LookAt shouldn't be called?
 
I found another weird thing with FinalIK grounder and moving platforms.

I haven't really looked into why it happens but the character goes through the platform:

MovingPlatformIKBug.gif
When I change the parameter "Max step" my character goes more or less through the platform (higher max step then more I go through the platform).
When the max step is set to something very high (example 5) my character falls through the platform.

I haven't really checked but my guess is that the grounder FBBIK component updates in Update while the character/moving platform update in FixedUpdate. Shouldn't grounder FBBIK be disabled and then updated manually in FinalIK Bridge like the other IK scripts?
 

Justin

Administrator
Staff member
The controller doesn't directly need to set anything on the grounder component and during my testing I found that it worked without any issues so that's why I didn't manually update it. I didn't try a moving platform though - if you're finding that it does need to be manually updated I can include that.
 
I was actually looking too much into it, thinking that something was wrong with the code. It took me a few hours of tinkering with the code to realize everything was good. The GrounderFBBIK component always updates at the same rate as FBBIK.

It turns out I had to add the "MovingPlatform" layer to the grounder solver... I wish I had thought of that before modifying the source code.

Everything works fine now.
 
Top