animations refactor
This commit is contained in:
166
Assets/jelycho/Code/Player/PlayerAnimator.cs
Normal file
166
Assets/jelycho/Code/Player/PlayerAnimator.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using RebootKit.Engine.Animations;
|
||||
using RebootReality.jelycho.Items;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Animations;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Playables;
|
||||
|
||||
namespace RebootReality.jelycho.Player {
|
||||
public struct PlayerLocomotionAnimatorParams {
|
||||
public float VelocityForwardNormalized;
|
||||
public float VelocityRightNormalized;
|
||||
public float TurnVelocity;
|
||||
public bool IsGrounded;
|
||||
}
|
||||
|
||||
public class CharacterHandsReAnimatorNode : IReAnimatorNode {
|
||||
enum State {
|
||||
None,
|
||||
Idle,
|
||||
QuickAttack
|
||||
}
|
||||
|
||||
[field: SerializeField] public string Name { get; private set; }
|
||||
|
||||
PlayableGraph m_Graph;
|
||||
AnimationMixerPlayable m_Mixer;
|
||||
AnimationClipPlayable m_CurrentPlayable;
|
||||
|
||||
ItemHandsAnimationClipsSet m_ClipsSet;
|
||||
|
||||
State m_State;
|
||||
|
||||
public event Action OnQuickAttackAnimationFinished = delegate { };
|
||||
|
||||
public void Tick(float deltaTime) {
|
||||
switch (m_State) {
|
||||
|
||||
case State.QuickAttack: {
|
||||
if (m_CurrentPlayable.GetTime() >= m_CurrentPlayable.GetAnimationClip().length &&
|
||||
m_CurrentPlayable.GetPlayState() == PlayState.Playing) {
|
||||
m_CurrentPlayable.Pause();
|
||||
OnQuickAttackAnimationFinished?.Invoke();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public IPlayable Build(PlayableGraph graph) {
|
||||
m_Graph = graph;
|
||||
m_Mixer = AnimationMixerPlayable.Create(graph, 1);
|
||||
return m_Mixer;
|
||||
}
|
||||
|
||||
public bool TryFindChild(string name, out IReAnimatorNode node) {
|
||||
node = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void UpdateClips(ItemHandsAnimationClipsSet clipsSet) {
|
||||
m_ClipsSet = clipsSet;
|
||||
|
||||
if (clipsSet == null) {
|
||||
m_State = State.None;
|
||||
return;
|
||||
}
|
||||
|
||||
SetIdle();
|
||||
}
|
||||
|
||||
public void PlayQuickAttack(int combo) {
|
||||
if (m_ClipsSet == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationClip clip = m_ClipsSet.quickAttacks[combo % m_ClipsSet.quickAttacks.Length];
|
||||
|
||||
m_CurrentPlayable = AnimationClipPlayable.Create(m_Graph, clip);
|
||||
|
||||
m_Mixer.DisconnectInput(0);
|
||||
m_Mixer.ConnectInput(0, m_CurrentPlayable, 0, 1.0f);
|
||||
|
||||
m_State = State.QuickAttack;
|
||||
m_CurrentPlayable.Play();
|
||||
}
|
||||
|
||||
public void SetIdle() {
|
||||
if (m_ClipsSet == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_CurrentPlayable = AnimationClipPlayable.Create(m_Graph, m_ClipsSet.idle);
|
||||
m_Mixer.DisconnectInput(0);
|
||||
m_Mixer.ConnectInput(0, m_CurrentPlayable, 0, 1.0f);
|
||||
|
||||
m_CurrentPlayable.Play();
|
||||
m_State = State.Idle;
|
||||
}
|
||||
}
|
||||
|
||||
public class PlayerAnimator : MonoBehaviour {
|
||||
[SerializeField] ReAnimator m_ReAnimator;
|
||||
|
||||
MixerNode m_LocomotionRootMixer;
|
||||
BlendTree2DNode m_GroundBlendTree;
|
||||
CharacterHandsReAnimatorNode m_Hands;
|
||||
|
||||
// @TODO: for some reason `SetLocomotionParams` is called before awake
|
||||
bool m_IsReady = false;
|
||||
|
||||
public UnityEvent onQuickAttackFinished = new UnityEvent();
|
||||
|
||||
void Awake() {
|
||||
m_LocomotionRootMixer = m_ReAnimator.FindNode<MixerNode>("locomotion_root");
|
||||
m_LocomotionRootMixer.SetInputWeight(0, 1.0f);
|
||||
m_LocomotionRootMixer.SetInputWeight(1, 0.0f);
|
||||
|
||||
m_GroundBlendTree = m_ReAnimator.FindNode<BlendTree2DNode>("locomotion_ground");
|
||||
m_GroundBlendTree.SetDirection(new float2(0, 1));
|
||||
|
||||
m_Hands = m_ReAnimator.FindNode<CharacterHandsReAnimatorNode>("hands");
|
||||
m_Hands.OnQuickAttackAnimationFinished += () => { onQuickAttackFinished?.Invoke(); };
|
||||
|
||||
m_IsReady = true;
|
||||
}
|
||||
|
||||
void Update() {
|
||||
|
||||
}
|
||||
|
||||
public void SetLocomotionParams(PlayerLocomotionAnimatorParams locomotionParams) {
|
||||
if (!m_IsReady) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_LocomotionRootMixer.SetInputWeight(0, locomotionParams.IsGrounded ? 1.0f : 0.0f);
|
||||
m_LocomotionRootMixer.SetInputWeight(1, locomotionParams.IsGrounded ? 0.0f : 1.0f);
|
||||
|
||||
float2 groundBlendDirection = new float2(locomotionParams.VelocityRightNormalized,
|
||||
locomotionParams.VelocityForwardNormalized);
|
||||
m_GroundBlendTree.SetDirection(groundBlendDirection);
|
||||
}
|
||||
|
||||
public void SetHandsAnimationSet(ItemHandsAnimationClipsSet clipsSet) {
|
||||
if (clipsSet == null) {
|
||||
m_ReAnimator.SetLayerWeight(1, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
m_ReAnimator.SetLayerWeight(1, 1.0f);
|
||||
m_Hands.UpdateClips(clipsSet);
|
||||
}
|
||||
|
||||
public void PlayQuickAttack(int combo) {
|
||||
m_Hands.PlayQuickAttack(combo);
|
||||
}
|
||||
|
||||
public void PlayHandsIdle() {
|
||||
m_Hands.SetIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user