private void Normals(Character.State state)
        {
            Vector3 normal = Vector3.up;

            if (Mathf.Approximately(state.isGrounded, 1.0f))
            {
                normal = this.character.transform.InverseTransformDirection(state.normal);
            }

            float paramNormalX = this.paramValues[HASH_NORMAL_X].Get(normal.x, NORMAL_SMOOTH);
            float paramNormalY = this.paramValues[HASH_NORMAL_Y].Get(normal.y, NORMAL_SMOOTH);
            float paramNormalZ = this.paramValues[HASH_NORMAL_Z].Get(normal.z, NORMAL_SMOOTH);

            this.animator.SetFloat(HASH_NORMAL_X, paramNormalX);
            this.animator.SetFloat(HASH_NORMAL_Y, paramNormalY);
            this.animator.SetFloat(HASH_NORMAL_Z, paramNormalZ);
        }
        private void Normals(Character.State state)
        {
            Vector3 normal = Vector3.up;

            if (state.isGrounded)
            {
                normal = this.character.transform.InverseTransformDirection(state.normal);
            }

            float paramNormalX = this.paramValues[this.paramHashNormalX].Get(normal.x, NORMAL_SMOOTH);
            float paramNormalY = this.paramValues[this.paramHashNormalY].Get(normal.y, NORMAL_SMOOTH);
            float paramNormalZ = this.paramValues[this.paramHashNormalZ].Get(normal.z, NORMAL_SMOOTH);

            this.animator.SetFloat(this.paramHashNormalX, paramNormalX);
            this.animator.SetFloat(this.paramHashNormalY, paramNormalY);
            this.animator.SetFloat(this.paramHashNormalZ, paramNormalZ);
        }
        // UPDATE: --------------------------------------------------------------------------------

        private void Update()
        {
            if (!this.animator.gameObject.activeInHierarchy)
            {
                return;
            }

            if (this.character == null)
            {
                throw new UnityException(EXC_NO_CHARACTER);
            }
            if (this.animator == null)
            {
                throw new UnityException(EXC_NO_ANIMATOR);
            }
            if (this.animEvents == null)
            {
                this.GenerateAnimatorEvents();
            }

            if (this.characterAttachments == null)
            {
                this.GenerateCharacterAttachments();
            }
            if (this.characterAnimation != null)
            {
                this.characterAnimation.Update();
            }

            if (this.useFootIK && this.footIK == null)
            {
                this.GenerateFootIK();
            }
            if (this.useHandIK && this.handIK == null)
            {
                this.GenerateHandIK();
            }
            if (this.useSmartHeadIK && this.headTrack == null)
            {
                if (this.GetHeadTracker() != null)
                {
                    this.headTrack.Untrack();
                }
            }

            Quaternion rotation = this.characterRotation.Update();

            Character.State state     = this.character.GetCharacterState();
            Vector3         direction = (!this.character.enabled || state.forwardSpeed.magnitude < 0.01f
                ? Vector3.zero
                : state.forwardSpeed
                                         );

            direction = Quaternion.Euler(0f, -rotation.eulerAngles.y, 0f) * direction;

            switch (this.character.IsRagdoll())
            {
            case true:
                rotation = this.animator.transform.localRotation;
                break;

            case false:
                rotation.eulerAngles = new Vector3(
                    rotation.eulerAngles.x,
                    Mathf.SmoothDampAngle(
                        this.animator.transform.localRotation.eulerAngles.y,
                        this.character.IsRagdoll()
                                ? this.animator.transform.localRotation.eulerAngles.y
                                : rotation.eulerAngles.y,
                        ref this.rotationVelocity, 1f
                        ),
                    rotation.eulerAngles.z
                    );
                break;
            }

            this.animator.transform.localRotation = rotation;
            direction = Vector3.Scale(direction, Vector3.one * (1.0f / this.character.characterLocomotion.runSpeed));

            float paramMoveForwardSpeed = this.paramValues[HASH_MOVE_FORWARD_SPEED].Get(direction.z, 0.1f);
            float paramMoveSidesSpeed   = this.paramValues[HASH_MOVE_SIDES_SPEED].Get(direction.x, 0.2f);
            float paramMovementSpeed    = this.paramValues[HASH_MOVEMENT_SPEED].Get(
                Vector3.Scale(direction, new Vector3(1, 0, 1)).magnitude,
                0.1f
                );

            float paramMoveTurnSpeed = this.paramValues[HASH_MOVE_TURN_SPEED].Get(state.pivotSpeed, 0.1f);
            float paramVerticalSpeed = this.paramValues[HASH_VERTICAL_SPEED].Get(state.verticalSpeed, 0.2f);
            float paramIsGrounded    = this.paramValues[HASH_IS_GROUNDED].Get(state.isGrounded, 0.1f);
            float paramIsSliding     = this.paramValues[HASH_IS_SLIDING].Get(state.isSliding, 0.1f);
            float paramIsDashing     = this.paramValues[HASH_IS_DASHING].Get(state.isDashing, 0.05f);
            float paramLandForce     = this.paramValues[HASH_LAND_FORCE].Get(0f, 2f);

            this.animator.SetFloat(HASH_MOVE_FORWARD_SPEED, paramMoveForwardSpeed);
            this.animator.SetFloat(HASH_MOVE_SIDES_SPEED, paramMoveSidesSpeed);
            this.animator.SetFloat(HASH_MOVE_TURN_SPEED, paramMoveTurnSpeed);
            this.animator.SetFloat(HASH_MOVEMENT_SPEED, paramMovementSpeed);
            this.animator.SetFloat(HASH_IS_GROUNDED, paramIsGrounded);
            this.animator.SetFloat(HASH_IS_SLIDING, paramIsSliding);
            this.animator.SetFloat(HASH_IS_DASHING, paramIsDashing);
            this.animator.SetFloat(HASH_VERTICAL_SPEED, paramVerticalSpeed);
            this.animator.SetFloat(HASH_TIME_SCALE, Time.timeScale);
            this.animator.SetFloat(HASH_LAND_FORCE, paramLandForce);

            this.Normals(state);
        }
        // UPDATE: --------------------------------------------------------------------------------

        private void Update()
        {
            if (this.character == null)
            {
                throw new UnityException(EXC_NO_CHARACTER);
            }
            if (this.animator == null)
            {
                throw new UnityException(EXC_NO_ANIMATOR);
            }
            if (this.animEvents == null)
            {
                this.GenerateAnimatorEvents();
            }
            if (this.characterAttachments == null)
            {
                this.GenerateCharacterAttachments();
            }
            if (this.characterAnimation != null)
            {
                this.characterAnimation.Update();
            }

            if (this.useFootIK && this.footIK == null)
            {
                this.GenerateFootIK();
            }
            if (this.useHandIK && this.handIK == null)
            {
                this.GenerateHandIK();
            }
            if (this.useSmartHeadIK && this.headTrack == null)
            {
                if (this.GetHeadTracker() != null)
                {
                    this.headTrack.Untrack();
                }
            }

            Character.State state     = this.character.GetCharacterState();
            Vector3         direction = (state.forwardSpeed.magnitude < 0.01f
                ? Vector3.zero
                : state.forwardSpeed
                                         );

            direction = Vector3.Scale(direction, Vector3.one * (1.0f / this.character.characterLocomotion.runSpeed));

            if (state.isGrounded && !this.wasGrounded)
            {
                float fallForceAmount = this.animator.GetFloat(this.paramHashVerticalSpeed);
                fallForceAmount = Mathf.Clamp01(fallForceAmount / MAX_FALL_FORCE_SPEED);
                this.paramValues[this.paramHashFallForce].Set(fallForceAmount);
            }

            float paramMoveForwardSpeed = this.paramValues[this.paramHashMoveForwardSpeed].Get(direction.z, 0.1f);
            float paramMoveSidesSpeed   = this.paramValues[this.paramHashMoveSidesSpeed].Get(direction.x, 0.2f);
            float paramMovementSpeed    = this.paramValues[this.paramHashMovementSpeed].Get(
                Vector3.Scale(direction, new Vector3(1, 0, 1)).magnitude,
                0.1f
                );
            float paramVerticalSpeed = this.paramValues[this.paramHashVerticalSpeed].Get(state.verticalSpeed, 0.1f);

            this.animator.SetFloat(this.paramHashMoveForwardSpeed, paramMoveForwardSpeed);
            this.animator.SetFloat(this.paramHashMoveSidesSpeed, paramMoveSidesSpeed);
            this.animator.SetFloat(this.paramHashMovementSpeed, paramMovementSpeed);
            this.animator.SetBool(this.paramHashIsGrounded, state.isGrounded);
            this.animator.SetFloat(this.paramHashVerticalSpeed, paramVerticalSpeed);
            this.animator.SetFloat(this.paramHashTimeScale, Time.timeScale);

            float paramFallForce = this.paramValues[this.paramHashFallForce].Get(0.0f, 0.25f);

            this.animator.SetFloat(this.paramHashFallForce, paramFallForce);

            if (this.character.characterLocomotion.faceDirection == CharacterLocomotion.FACE_DIRECTION.MovementDirection)
            {
                float paramTargetLock = this.paramValues[this.paramHashTargetLock].Get(0.0f, 0.1f);
                this.animator.SetFloat(this.paramHashTargetLock, paramTargetLock);
            }
            else
            {
                float paramTargetLock = this.paramValues[this.paramHashTargetLock].Get(1.0f, 0.1f);
                this.animator.SetFloat(this.paramHashTargetLock, paramTargetLock);
            }

            this.Normals(state);
            this.wasGrounded = state.isGrounded;
        }