UNITY3D TOOLS AND SCRIPTS


EASY ROOT MOTION FOR UNITY3D

Asset Store URL: https://assetstore.unity.com/packages/slug/202036

This asset configures the Unity3D Animator to work with a custom root motion algorithm.

The main feature of this asset is that it doesn't need the root bone of all animations to be in the same position in all animations.

REQUIREMENTS

KNOWN ISSUES

These implementations are not tested with the Unity IK system.

YOUTUBE VIDEO

The video below shows the asset features:



The video below shows the mini-game that comes as example inside the asset:

1 HOW DOES THE PLUGIN WORKS

You can see the plugin hierarchy below:


There are two components:

1.1 ROOT MOTION PROCESSOR

You need to put the RootMotionProcessor at the same GameObject the Animator is.

Click in the 'Process All Animator Clips' as shown in the image below:


It will process the Unity Animator states and clips and will generate a log as shown in the image below:


The plugin will search for the root node by checking the first node in the model hierarchy that have animation on it.

NOTICE: Every time you change the animator state or clip, you need to click in the 'Process All Animator Clips' again.

1.2 ANIMATION MOTION

The AnimationMotion component will generate the move by changing the current GameObject Transform.

You can put it on any parent level of the RootMotionProcessor.

Take a look at the image below:


When you click in the 'Query Clip Motion Influence Names' it will generate the parameters the root motion will use to move the GameObject.

Take a look at the image below:


These parameters are related to the 'Animator' local space. They are the amount of the animation you will consider to move the GameObject.

The parameter '0' means that this axis in the 'Animator' local space will be only played without move the object.

The parameter '1.0' means that this axis in the 'Animator' local space will be used to move the object.

1.3 CUSTOMIZING THE ANIMATION MOTION

It is possible to customize the AnimationMotion result by implementing a method, delegate or lambda function and add it to the AnimationMotion.OnMove event.

This event will pass the motion vectors and the final position to your method.

This allows you to implement a custom move method.

The first three parameters are in the 'Animator' local space and the last is in the world space.

Take a look at the example below:
    using MilkyWay;
    using MilkyWay.RootMotionUtil;
    using UnityEngine;

    [RequireComponent(typeof(AnimationMotion))]
    public class CustomAnimationMotion : MonoBehaviour
    {
        AnimationMotion animationMotion;
        Transform animator_transform;

        public LayerMask collisionLayerMask;
        public int maxSlideSteps = 5;

        void Awake()
        {
            animationMotion = GetComponent<AnimationMotion>();
            animator_transform = animationMotion.rootMotionProcessor.transform;
        }

        void OnEnable()
        {
            animationMotion.OnMove += AnimationMotion_OnMove;
        }

        void OnDisable()
        {
            if (animationMotion != null)
                animationMotion.OnMove -= AnimationMotion_OnMove;
        }

        private void AnimationMotion_OnMove(float animator_right_factor,
            float animator_up_factor, float animator_forward_factor,
            Vector3 world_position)
        {
            // Custom move implementation...
            Vector3 target_vector = animator_transform.forward * animator_forward_factor;
            
            Vector3 point1, point2;
            float radius;

            Enhanced.ExtractCapsuleInformation(capsuleCollider, 
                out point1, out point2, out radius);

            Enhanced.Instance.MoveTransformUsingCapsule(transform, 
                point1, point2, radius, 
                target_vector, maxSlideSteps, 
                collisionLayerMask);
        }
    }

2 BONUS SCRIPTS AT MilkyWay.RootMotionUtil NAMESPACE

There are three problems when you deal with custom character move in Unity3D.

We have the Enhanced class to deal with these problems.

2.1 ENHANCED CLASS

This class has an enhanced version of the Physics.BoxCast, Physics.CapsuleCast and Physics.SphereCast.

They are:
In addition to these implementations, there are also three methods to calculate a character's movement using the box, capsule or sphere. These move methods don't use the physic materials.

They are:
There are also three other methods to extract information from the BoxCollider, CapsuleCollider or SphereCollider to use in the basic collision algorithms.

They are:
The example can be seen in the 1.3 CUSTOMIZING THE ANIMATION MOTION section of this document.

2.2 PRESS RELEASE DETECTOR CLASS

This is a pure C# class to aid in the detection of a rising edge (up) or a falling edge (down) of a boolean signal.

This allow us to simplify our input analysis.

Take a look at the example below:

    using MilkyWay.RootMotionUtil;
    using UnityEngine;

    public class ThirdPersonPlayerController : MonoBehaviour
    {
        // ...

        PressReleaseDetector walk = new PressReleaseDetector();
        PressReleaseDetector run = new PressReleaseDetector();
        PressReleaseDetector right = new PressReleaseDetector();
        PressReleaseDetector left = new PressReleaseDetector();
        
        void Update()
        {
            // set the state of all analysers
            right.SetState(Input.GetKey(KeyCode.A));
            left.SetState(Input.GetKey(KeyCode.D));
            walk.SetState(Input.GetKey(KeyCode.W) || (right.pressed ^ left.pressed) );
            run.SetState(Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.LeftShift));

            // execute the logic based on the analysers result
            if (run.down) {
                // run state activation ...
            } else if ( walk.down || (walk.pressed && run.up) ) {
                // walk state activation ...
            } else if ( walk.up || run.up) {
                // idle state activation ...
            }

            if (right.pressed ^ left.pressed)
            {
                if (right.pressed) {
                    // rotate right ...
                } else if (left.pressed) {
                    // rotate left ...
                }
            }
        }
    }

3 EXAMPLES

There are three examples in the asset:

4 DEALING WITH ROOT ANIMATIONS FROM BLENDER'S FBX EXPORTER

The official Blender's FBX exporter exports a 'ghost' root node called 'Armature'.

It makes the plugin to behave wrong because it doesn't detect the right root node of the animation.

You can use the following modification on the Blender's plugin to deal with this issue:

https://github.com/A-Ribeiro/CustomBlenderFBXExporter

CONTACT INFORMATION

contact @ unity.mwaystudio.com

Copyright @ 2024