replaced zombie model, working on animations

This commit is contained in:
2025-10-02 00:38:29 +02:00
parent 8a84bd459f
commit c3cea92041
38 changed files with 2304 additions and 3726 deletions

View File

@@ -373,14 +373,17 @@ namespace RebootReality.jelycho.Enemies {
}
///
/// @MARK: Utility
/// @MARK: Editor Utility
///
#if UNITY_EDITOR
[Button]
void SetupHurtboxes() {
foreach (ZombieHurtbox hurtbox in GetComponentsInChildren<ZombieHurtbox>()) {
hurtbox.owner = this;
UnityEditor.EditorUtility.SetDirty(hurtbox);
}
}
#endif
}
enum ZombieActorEvents {

View File

@@ -128,7 +128,6 @@ namespace RebootReality.jelycho.Player {
}
private set {
s_Logger.Info("NEW");
m_TargetInteractable = value;
OnTargetInteractableChanged(value);
}
@@ -659,23 +658,17 @@ namespace RebootReality.jelycho.Player {
m_CurrentCameraBobbing = Mathf.MoveTowards(m_CurrentCameraBobbing,
m_TargetCameraBobbing,
m_CameraBobbingTransitionSpeed * deltaTime);
// m_Camera.SetBobbing(m_CurrentCameraBobbing);
m_Camera.SetBobbing(0.0f);
m_Camera.SetBobbing(m_CurrentCameraBobbing);
// m_CameraSpring.UpdateSpring(deltaTime,
// m_CharacterForwardTransform.up,
// m_CharacterForwardTransform.right,
// m_CharacterForwardTransform.forward);
m_CameraSpring.UpdateSpring(deltaTime,
m_CharacterForwardTransform.up,
m_CharacterForwardTransform.right,
m_CharacterForwardTransform.forward);
}
void SenseInteractable() {
IInteractable interactable = m_InteractablesSensor.Sense();
if (interactable != null) {
s_Logger.Info("NOT NULL");
}
if (interactable != TargetInteractable) {
s_Logger.Info("sensed different interactable");
TargetInteractable = interactable;
}
}

View File

@@ -1,12 +1,13 @@
using System;
using System.Runtime.CompilerServices;
using Animancer;
using RebootKit.Engine.Animations;
using RebootReality.jelycho.Items;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Events;
using UnityEngine.Playables;
using UnityEvent = UnityEngine.Events.UnityEvent;
namespace RebootReality.jelycho.Player {
public struct PlayerLocomotionAnimatorParams {
@@ -127,7 +128,7 @@ namespace RebootReality.jelycho.Player {
}
}
public class CharacterHandsReAnimatorNode : IReAnimatorNode {
public class PlayerHandsAnimator {
enum State {
None,
Idle,
@@ -137,12 +138,9 @@ namespace RebootReality.jelycho.Player {
Charged,
ChargedUse
}
[field: SerializeField] public string Name { get; private set; }
PlayableGraph m_Graph;
AnimationMixerPlayable m_Mixer;
AnimationClipPlayable m_CurrentPlayable;
AnimancerLayer m_AnimancerLayer;
AnimancerState m_AnimancerState;
ItemHandsAnimationClipsSet m_ClipsSet;
@@ -150,13 +148,23 @@ namespace RebootReality.jelycho.Player {
public event Action OnQuickAttackAnimationFinished = delegate { };
public event Action OnCharged = delegate { };
public PlayerHandsAnimator(AnimancerLayer layer) {
m_AnimancerLayer = layer;
}
public void Tick(float deltaTime) {
if (m_AnimancerState == null) {
return;
}
switch (m_State) {
case State.QuickAttack: {
if (IsCurrentClipFinished() && m_CurrentPlayable.GetPlayState() == PlayState.Playing) {
m_CurrentPlayable.Pause();
if (IsCurrentClipFinished()) {
Debug.Log("QUICK ATTACK FINISHEDDD");
m_AnimancerState.Stop();
m_AnimancerState = null;
OnQuickAttackAnimationFinished?.Invoke();
}
break;
@@ -179,17 +187,6 @@ namespace RebootReality.jelycho.Player {
}
}
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;
@@ -207,26 +204,17 @@ namespace RebootReality.jelycho.Player {
}
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_AnimancerState = m_AnimancerLayer.Play(clip);
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_AnimancerState = m_AnimancerLayer.Play(m_ClipsSet.idle);
m_State = State.Idle;
}
@@ -235,11 +223,7 @@ namespace RebootReality.jelycho.Player {
return;
}
m_CurrentPlayable = AnimationClipPlayable.Create(m_Graph, m_ClipsSet.charging);
m_Mixer.DisconnectInput(0);
m_Mixer.ConnectInput(0, m_CurrentPlayable, 0, 1.0f);
m_CurrentPlayable.Play();
m_AnimancerState = m_AnimancerLayer.Play(m_ClipsSet.charging);
m_State = State.Charging;
}
@@ -248,11 +232,7 @@ namespace RebootReality.jelycho.Player {
return;
}
m_CurrentPlayable = AnimationClipPlayable.Create(m_Graph, m_ClipsSet.chargedIdle);
m_Mixer.DisconnectInput(0);
m_Mixer.ConnectInput(0, m_CurrentPlayable, 0, 1.0f);
m_CurrentPlayable.Play();
m_AnimancerState = m_AnimancerLayer.Play(m_ClipsSet.chargedIdle);
m_State = State.ChargedIdle;
}
@@ -261,79 +241,103 @@ namespace RebootReality.jelycho.Player {
return;
}
m_CurrentPlayable = AnimationClipPlayable.Create(m_Graph, m_ClipsSet.chargedUse);
m_Mixer.DisconnectInput(0);
m_Mixer.ConnectInput(0, m_CurrentPlayable, 0, 1.0f);
m_CurrentPlayable.Play();
m_AnimancerState = m_AnimancerLayer.Play(m_ClipsSet.chargedUse);
m_State = State.ChargedUse;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
bool IsCurrentClipFinished() {
return m_CurrentPlayable.GetTime() >= m_CurrentPlayable.GetAnimationClip().length;
return m_AnimancerState.NormalizedTime >= 1.0f;
}
}
public class PlayerAnimator : MonoBehaviour {
[SerializeField] ReAnimator m_ReAnimator;
[SerializeField] int m_HandsLayerIndex = 2;
LayerMixerNode m_LegsLayerMixer;
BasicCharacterLocomotionReAnimatorNode m_GroundBlendTree;
CharacterHandsReAnimatorNode m_Hands;
AnimationClipNode m_QuickKickNode;
[SerializeField] AnimancerComponent m_Animancer;
[SerializeField] AnimationClip m_IdleClip;
[SerializeField] TransitionAsset m_GroundLocomotion;
[SerializeField] StringAsset m_GroundLocomotionPropertyX;
[SerializeField] StringAsset m_GroundLocomotionPropertyY;
SmoothedVector2Parameter m_SmoothLocomotionDirection;
[SerializeField] AvatarMask m_HandsMask;
AnimancerLayer m_LocomotionLayer;
AnimancerLayer m_HandsLayer;
PlayerHandsAnimator m_Hands;
// @TODO: for some reason `SetLocomotionParams` is called before awake
bool m_IsReady = false;
public UnityEvent onQuickAttackFinished = new UnityEvent();
public UnityEvent onChargeReady = new UnityEvent();
void Awake() {
m_LegsLayerMixer = m_ReAnimator.FindNode<LayerMixerNode>("legs_mixer");
m_LegsLayerMixer.SetLayerWeight(0, 1.0f);
m_LegsLayerMixer.SetLayerWeight(1, 0.0f);
m_LegsLayerMixer.SetLayerWeight(2, 0.0f);
m_GroundBlendTree = m_ReAnimator.FindNode<BasicCharacterLocomotionReAnimatorNode>("legs_locomotion_ground");
m_GroundBlendTree.SetInput(new float2(0, 0), 0.0f);
m_Hands = m_ReAnimator.FindNode<CharacterHandsReAnimatorNode>("hands");
m_Hands.OnQuickAttackAnimationFinished += () => { onQuickAttackFinished?.Invoke(); };
m_Hands.OnCharged += () => { onChargeReady?.Invoke(); };
m_QuickKickNode = m_ReAnimator.FindNode<AnimationClipNode>("legs_kick_quick");
m_LocomotionLayer = m_Animancer.Layers[0];
m_HandsLayer = m_Animancer.Layers[1];
m_LocomotionLayer.SetDebugName("Locomotion");
m_HandsLayer.SetDebugName("Hands");
m_HandsLayer.Mask = m_HandsMask;
m_Hands = new PlayerHandsAnimator(m_HandsLayer);
m_Hands.OnQuickAttackAnimationFinished += () => onQuickAttackFinished.Invoke();
m_Hands.OnCharged += () => onChargeReady.Invoke();
m_SmoothLocomotionDirection = new SmoothedVector2Parameter(m_Animancer,
m_GroundLocomotionPropertyX,
m_GroundLocomotionPropertyY,
0.1f);
m_LocomotionLayer.Play(m_GroundLocomotion);
m_HandsLayer.SetWeight(0.0f);
m_IsReady = true;
}
void OnDestroy() {
m_SmoothLocomotionDirection.Dispose();
}
void Update() {
float dt = Time.deltaTime;
m_Hands.Tick(dt);
}
public void SetLocomotionParams(PlayerLocomotionAnimatorParams locomotionParams) {
if (!m_IsReady) {
return;
}
m_LegsLayerMixer.SetLayerWeight(1, locomotionParams.IsGrounded ? 0.0f : 1.0f);
//m_LegsLayerMixer.SetLayerWeight(1, locomotionParams.IsGrounded ? 0.0f : 1.0f);
var groundBlendDirection = new float2(locomotionParams.VelocityRightNormalized,
locomotionParams.VelocityForwardNormalized);
m_GroundBlendTree.SetInput(groundBlendDirection, locomotionParams.TurnVelocity);
}
//m_GroundBlendTree.SetInput(groundBlendDirection, locomotionParams.TurnVelocity);
m_SmoothLocomotionDirection.TargetValue = groundBlendDirection;
}
public void SetHandsAnimationSet(ItemHandsAnimationClipsSet clipsSet) {
if (clipsSet == null) {
m_ReAnimator.SetLayerWeight(m_HandsLayerIndex, 0.0f);
m_HandsLayer.SetWeight(0.0f);
return;
}
m_ReAnimator.SetLayerWeight(m_HandsLayerIndex, 1.0f);
m_HandsLayer.SetWeight(1.0f);
m_Hands.UpdateClips(clipsSet);
}
public void PlayQuickAttack(int combo) {
// int index = combo % m_ItemHandsClips.quickAttacks.Length;
// AnimancerState state = m_HandsLayer.Play(m_ItemHandsClips.quickAttacks[index]);
// state.Events(this).OnEnd ??= OnQuickAttackAnimationEnd;
m_Hands.PlayQuickAttack(combo);
}
// void OnQuickAttackAnimationEnd() {
// PlayHandsIdle();
// onQuickAttackFinished?.Invoke();
// }
public void PlayHandsIdle() {
m_Hands.SetIdle();
@@ -348,11 +352,11 @@ namespace RebootReality.jelycho.Player {
}
public void PlayKickAnimation() {
m_LegsLayerMixer.SetLayerWeight(2, 1.0f);
// m_LegsLayerMixer.SetLayerWeight(2, 1.0f);
m_QuickKickNode.PlayOnceWithCallback(() => {
m_LegsLayerMixer.SetLayerWeight(2, 0.0f);
});
// m_QuickKickNode.PlayOnceWithCallback(() => {
// m_LegsLayerMixer.SetLayerWeight(2, 0.0f);
// });
}
}
}