Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Character Cloth with Final IK (with GIFs)
#1
Triste 
This is how it looks without obiCloth
The cloth weight is transferred from the rigged character as I followed from the TrenchCoat Example.

*Final IK + Grounder has been used

[Image: giphy.gif]

Once I attached the ObiCloth this happens.

[Image: giphy.gif]

This is how I set up based on your tutorial webpage

Obi Solver on the Character Root
Obi Cloth on the Skinned Mesh Object

*Player Object is a root

[Image: JnxT8mX.jpg]

[Image: xzJ9dEm.jpg]

Setting on the Animator on the root (Player) 

What I used
- Obi Slover
- Final IK FBBIK
- Grounder

[Image: 3oWDD0j.jpg]

This is the Script Execution Order

[Image: UI52Gne.jpg]

Please Help! I try to solve this problem for a week but I can't.
Thank you in advance!
Reply
#2
I'm not quite sure but I find out the thing that could make this happened.

The "Obi Animator Controller" has been added into my GameObject later after I played the scene.
Turn this component off makes my obiCloth animation works flawlessly with Final IK. Lengua
Reply
#3
I find new issues when using multiple ObiSolver.

I have 2 ObiSolvers
 - one for the Character
 - one for the Flags

When I play the scene, The Character display the cloth incorrectly so I have to turn off the Flag Obi Solver first in order to get the right position for my character. Then I can turn on the Flag again. I don't know what is happening Triste
Reply
#4
Hey, developer of Final IK here...

ObiCloth disables the Animator and updates it via ObiAnimatorController when the Obi solver begins, then feeds the results to the cloth for processing. That does not allow Final IK to be updated after the animation and before the cloth simulation, so it will be out of sync no matter how you set up the Script Execution Order.

So basically, you will need to make sure that whenever Animator is updated, Final IK will also be updated and that must be before the cloth solver begins. To do that, you'll need to make a few changes to ObiAnimatorController.cs.
First, add 
Code:
using RootMotion.FinalIK;
to the top of the file. It will not compile, because Obi uses assembly definition files. So you'll also need to create assembly definitions for Final IK:

1. Add a new assembly definition file (Create/Assembly Definition) to Plugins/RootMotion, name it "RootMotion". Then another one to Plugins/RootMotion/Editor, name it "RootMotionEditor". 
2. Select the RootMotionEditor.asmdef file, add RootMotion.asmdef to the Assembly Definition References, deselect every platform except Editor.
3. Go to Obi/Scripts/Obi.asmdef and add RootMotion.asmdef to it's Assembly Defition References.
4. If you get an error about some ScriptableObject stuff when you select an object with IK, just right-click on Plugins/RootMotion and select Reimport, it's a Unity bug.

Now you can reference RootMotion scripts from Obi scripts. continue to edit ObiAnimatorController like so:

1. Add this:


Code:
public IK[] IKComponents;

       private void Start()
       {
           foreach (IK ik in IKComponents)
           {
               ik.enabled = false;
           }
       }

2. Add this to the line just after animator.Update(updateDelta);

Code:
foreach (IK ik in IKComponents)
               {
                   ik.GetIKSolver().Update();
               }

3. Assign all the IK components you wish to use to the ObiAnimatorController in the Editor.


That makes sure the IK components get updated in sync with Obi.
Reply
#5
Hi,

Just chiming in to clarify some of the things said in this thread. Thanks to Partel for contributing a solution!


Quote:The "Obi Animator Controller" has been added into my GameObject later after I played the scene.
Turn this component off makes my obiCloth animation works flawlessly with Final IK. Lengua

Disabling the ObiAnimationController is not a good idea. It makes sure to update the Animator right before cloth simulation takes place, so disabling it can introduce a delay between animation and simulation (due to animation happening after simulation each frame, instead of before). This is the order in which things should happen every frame:

- Unity's Animator component updates bone positions.
- FinalIK applies IK constraints to bones.
- Obi uses bone transforms to update cloth simulation.

Partel's solution will work, as it achieves this update order.

Edit: a minor hint though: creating an event delegate in ObiAnimatorController.cs and calling it before animator.Update will allow you to hook custom code after the animator is updated. In 4.1, modifying the animator like this:

Code:
using UnityEngine;
using System;

namespace Obi
{
    [RequireComponent(typeof(Animator))]
    [DisallowMultipleComponent]
    public class ObiAnimatorController : MonoBehaviour
    {
        private Animator animator;
        private float lastUpdate;
        private float updateDelta;

        public event System.EventHandler OnAnimatorUpdated;

        public float UpdateDelta{
            get{return updateDelta;}
        }

        public void Awake(){
            animator = GetComponent<Animator>();
            lastUpdate = Time.time;
        }

        public void OnDisable(){
            ResumeAutonomousUpdate();
        }

        public void UpdateAnimation(bool fixedUpdate)
        {
            // UpdateAnimation might becalled during FixedUpdate(), but we still need to account for the full frame's worth of animation.
            // Since Time.deltaTime returns the fixed step during FixedUpdate(), we need to use our own delta.
            updateDelta = Time.time - lastUpdate;
            lastUpdate = Time.time;

            if (animator.updateMode == AnimatorUpdateMode.AnimatePhysics)
                updateDelta = Time.fixedDeltaTime;

            // Note: when using AnimatorUpdateMode.Normal, the update method of your character controller
            // should be Update() instead of FixedUpdate() (ObiCharacterController.cs, in this case).

            if (animator != null && isActiveAndEnabled && (animator.updateMode != AnimatorUpdateMode.AnimatePhysics || fixedUpdate)){
                animator.enabled = false;
                animator.Update(updateDelta);

                if (OnAnimatorUpdated != null)
                    OnAnimatorUpdated(this,EventArgs.Empty);
            }
        }

        public void ResumeAutonomousUpdate(){
            if (animator != null){
                animator.enabled = true;
            }
        }
    }
}

allows you to do:

Code:
animationController.OnAnimatorUpdated += <custom function here>;

So, you can do this instead of having to create an assembly definition file for FinalIK:

Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RootMotion.FinalIK;
using Obi;

public class FinalIKUpdater : MonoBehaviour {

    public ObiAnimatorController controller;
    public IK[] IKComponents;

    void Start () {

        foreach (IK ik in IKComponents)
            ik.enabled = false;
       
        controller.OnAnimatorUpdated += UpdateFinalIKSolvers;
    }

    void UpdateFinalIKSolvers (object sender, System.EventArgs e)
    {
        foreach (IK ik in IKComponents)
         ik.GetIKSolver().Update();
    }

}
Reply
#6
(15-04-2019, 10:07 AM)Partel Lang Wrote: Hey, developer of Final IK here...

ObiCloth disables the Animator and updates it via ObiAnimatorController when the Obi solver begins, then feeds the results to the cloth for processing. That does not allow Final IK to be updated after the animation and before the cloth simulation, so it will be out of sync no matter how you set up the Script Execution Order.

So basically, you will need to make sure that whenever Animator is updated, Final IK will also be updated and that must be before the cloth solver begins. To do that, you'll need to make a few changes to ObiAnimatorController.cs.
First, add 
Code:
using RootMotion.FinalIK;
to the top of the file. It will not compile, because Obi uses assembly definition files. So you'll also need to create assembly definitions for Final IK:

1. Add a new assembly definition file (Create/Assembly Definition) to Plugins/RootMotion, name it "RootMotion". Then another one to Plugins/RootMotion/Editor, name it "RootMotionEditor". 
2. Select the RootMotionEditor.asmdef file, add RootMotion.asmdef to the Assembly Definition References, deselect every platform except Editor.
3. Go to Obi/Scripts/Obi.asmdef and add RootMotion.asmdef to it's Assembly Defition References.
4. If you get an error about some ScriptableObject stuff when you select an object with IK, just right-click on Plugins/RootMotion and select Reimport, it's a Unity bug.

Now you can reference RootMotion scripts from Obi scripts. continue to edit ObiAnimatorController like so:

1. Add this:


Code:
public IK[] IKComponents;

       private void Start()
       {
           foreach (IK ik in IKComponents)
           {
               ik.enabled = false;
           }
       }

2. Add this to the line just after animator.Update(updateDelta);

Code:
foreach (IK ik in IKComponents)
               {
                   ik.GetIKSolver().Update();
               }

3. Assign all the IK components you wish to use to the ObiAnimatorController in the Editor.


That makes sure the IK components get updated in sync with Obi.

Hi Pärtel
What to do with VRIK? Invoking IK Update from somewhere else seems to make my avatar want to walk towards the ceiling. Anyways I don't have an Animator.
Sort of same thing like when I turn Fix Transform off.
Thank you for trying to help us out with this.
Reply
#7
I'm glad to have followed this thread, as the approaches above have helped.  However, I still haven't found the magic sauce that ensures the clothing stays where it is supposed to stay, when the model is moved around.

[Image: pwEV7be.jpg]

I am using the approach laid out by Partel Lang and josemendez above; namely hooking the body-posing and body-positioning corrections within the Obi Animator Controller rather than relying on the normal Unity ordering.  The script ordering is also stacked as shown with all the Obi getting the final say.

The script which moves the whole body root is looking at the objects which drive foot IK positions, and deciding where the whole body should be.  I have called this before and after the actual IK pose-adjusting steps, I have tried using FixedUpdate, AfterFixedUpdate, LateUpdate in the solver.  I tried World Space, and Local Space, for the Solver.  I think since all of the positioning is done within the Obi Animator Controller this doesn't make much difference at the overall level.

If you look at the Obi Cloth object, the shirt, the majority of the shirt is fixed and the bottom rows are unfixed to deform. This part works relatively smoothly.  The issue is that the entire shirt moves relative to the chest and shoulders as the hips bone moves relative to the main object. If I drag the foot down below the floor, the hips and spine follow downward and give an even more exaggerated effect than this screenshot.  Even if I never move the main object (parent of armature), moving the hips (first child of armature) creates this disconnect.
Reply
#8
Hey,

About VRIK and the character climbing to the ceiling bug, I forgot about the Fix Transforms part.
If the avatar does not have animation playing on it that would overwrite the results of IK the next frame, the IK will start solving additively on top of its own results frame by frame. The solution would be to add this to ObiAnimatorController.cs, just before animator.Update(updateDelta) is called:

Code:
foreach (IK ik in IKComponents)
               {
                   if (ik.fixTransforms) ik.GetIKSolver().FixTransforms();
               }

And make sure you have "Fix Transforms" enabled in the VRIK component.

Best,
Pärtel
Reply
#9
(17-05-2019, 10:29 AM)Partel Lang Wrote: Hey,

About VRIK and the character climbing to the ceiling bug, I forgot about the Fix Transforms part.
If the avatar does not have animation playing on it that would overwrite the results of IK the next frame, the IK will start solving additively on top of its own results frame by frame. The solution would be to add this to ObiAnimatorController.cs, just before animator.Update(updateDelta) is called:

Code:
foreach (IK ik in IKComponents)
               {
                   if (ik.fixTransforms) ik.GetIKSolver().FixTransforms();
               }

And make sure you have "Fix Transforms" enabled in the VRIK component.

Best,
Pärtel

Thank you Pärtel,
That solved it.
I almost guessed it and didn't have a clue Gran sonrisa
And of course - thank you Jose.
-Jim
Reply