110 lines
4.7 KiB
C#

using System.Collections.Generic;
using UnityEngine;
using UnityEditor.Animations;
namespace CreatureControl {
public class CreatureAnimator : MonoBehaviour {
public Creature creature;
public RuntimeAnimatorController animatorController;
private Animator animator;
public enum RootMotionMode {
Normal,
Inverse
};
public RootMotionMode rootMotionMode = RootMotionMode.Normal;
[System.Serializable]
public class RootMotion {
public string clipName;
public Vector3 linearVelocity;
public Vector3 angularVelocity;
public readonly static RootMotion zero = new() {
linearVelocity = Vector3.zero,
angularVelocity = Vector3.zero
};
}
//public Dictionary<string, RootMotion> rootVelocities = new();
public List<RootMotion> rootVelocities = new();
public RootMotion GetRootMotion(string name) {
return this.rootVelocities.Find(rm => rm.clipName == name);
}
public Dictionary<Vector3, string> animationDirections = new();
protected virtual void Awake() {
this.creature = GetComponent<Creature>();
this.animator = creature.animator; // GetComponent<Animator>();
this.animator.applyRootMotion = this.rootMotionMode == RootMotionMode.Normal;
}
protected virtual void Update() {
if (rootMotionMode == RootMotionMode.Inverse) {
Vector3 speed = new(0, 0, 0.024f);
this.transform.localPosition += speed * Time.deltaTime; //0.0048f * Time.deltaTime * this.transform.forward;
InverseRootMotionUpdate();
}
else {
this.animator.SetFloat("Forward", 1f);
// Ensure that the pose of the model matches the target rig
this.creature.targetRig.transform.GetPositionAndRotation(out Vector3 targetRigPosition, out Quaternion targetRigOrientation);
this.creature.transform.SetPositionAndRotation(targetRigPosition, targetRigOrientation);
this.creature.targetRig.transform.SetPositionAndRotation(targetRigPosition, targetRigOrientation);
}
}
private Vector3 lastPosition;
protected void InverseRootMotionUpdate() {
if (lastPosition.sqrMagnitude > 0) {
Vector3 translation = this.transform.position - lastPosition;
Vector3 worldVelocity = translation / Time.deltaTime;
Vector3 localVelocity = transform.InverseTransformDirection(worldVelocity);
RootMotion rootMotion = this.GetRootMotion("AntWalkForward");
Vector3 animationVelocity = rootMotion.linearVelocity; // rootVelocities["AntWalkForward"].linearVelocity;
float fwdAnimationSpeed = localVelocity.z / animationVelocity.z;
this.animator.SetFloat("Forward", fwdAnimationSpeed);
}
lastPosition = this.transform.position;
}
void RetrieveBlendTreeAnimations(Animator animator, string parameterName, float targetValue) {
AnimatorController ac = animator.runtimeAnimatorController as AnimatorController;
// Check if the Animator Controller is valid
if (ac == null) {
Debug.LogError("Animator Controller is not set correctly.");
return;
}
// Iterate through each layer in the Animator Controller
foreach (AnimatorControllerLayer layer in ac.layers) {
// Access the state machine
foreach (ChildAnimatorState state in layer.stateMachine.states) {
// Check if the state contains a Blend Tree
if (state.state.motion is BlendTree blendTree) {
// Iterate through blend tree children
foreach (ChildMotion child in blendTree.children) {
if (child.directBlendParameter == parameterName) {
// Simulate parameter setting
//animator.SetFloat(parameterName, targetValue);
// Get the animation clip information
if (child.motion is AnimationClip clip) {
Debug.Log($"Animation Clip: {clip.name}, Speed: {child.timeScale}");
}
}
}
}
}
}
}
}
}