FantasyAsset/Assets/Scripts/Enemy/EnemyAnimationController.cs
TG9six bb58f5ed86 Visual Changes
Added NPCs for wave, added animations, added impact vfx for fireball
2025-09-02 20:39:37 +04:00

179 lines
4.7 KiB
C#

using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(Animator))]
public class EnemyAnimationController : MonoBehaviour
{
[Header("State Names")]
public string idleState = "monster_idle_1";
public string walkState = "monster_Walking";
public string runState = "monster_Run";
public string walkBackState = "monster_Walk_Back";
public string[] attackStates = { "monster_attack_1", "monster_attack_2", "monster_attack_3" };
public string[] hitStates = { "monster_hit_1", "monster_hit_2" };
public string angerState = "monster_anger";
public string deathState = "monster_Death";
[Header("Locomotion")]
public int layerIndex = 0;
public float walkSpeed = 0.15f;
public float runSpeed = 2.0f;
public float crossFade = 0.08f;
[Header("Stability")]
public float walkToIdleDown = 0.08f;
public float runToWalkDown = 1.7f;
public float speedSmoothTime = 0.1f;
public float minActionLock = 0.15f;
Animator anim;
NavMeshAgent agent; CharacterController cc; Rigidbody rb;
string currentState = "";
float smoothedSpeed, speedVel;
bool inAction;
float actionUnlockTime;
string actionState;
void Awake()
{
anim = GetComponent<Animator>();
agent =transform.parent.GetComponent<NavMeshAgent>();
cc = transform.parent.GetComponent<CharacterController>();
rb = transform.parent.GetComponent<Rigidbody>();
}
void Update()
{
if (inAction) TryAutoUnlockFromAction();
UpdateLocomotion();
}
void UpdateLocomotion()
{
if (inAction) return;
float rawSpeed = GetHorizSpeed();
smoothedSpeed = Mathf.SmoothDamp(smoothedSpeed, rawSpeed, ref speedVel, speedSmoothTime);
string target = string.IsNullOrEmpty(currentState) ? idleState : currentState;
if (currentState == idleState || string.IsNullOrEmpty(currentState))
{
if (smoothedSpeed > walkSpeed) target = walkState;
else target = idleState;
}
else if (currentState == walkState)
{
if (smoothedSpeed > runSpeed) target = runState;
else if (smoothedSpeed < walkToIdleDown) target = idleState;
}
else if (currentState == runState)
{
if (smoothedSpeed < runToWalkDown) target = walkState;
}
else
{
if (smoothedSpeed <= walkToIdleDown) target = idleState;
}
if (target != currentState && !anim.IsInTransition(layerIndex))
{
anim.CrossFade(target, crossFade, layerIndex);
currentState = target;
}
}
float GetHorizSpeed()
{
if (agent) return agent.velocity.magnitude;
if (cc) return cc.velocity.magnitude;
if (rb) return new Vector3(rb.velocity.x, 0f, rb.velocity.z).magnitude;
return 0f;
}
void BeginAction(string stateName)
{
if (!anim.IsInTransition(layerIndex))
{
anim.CrossFade(stateName, crossFade, layerIndex);
currentState = stateName;
inAction = true;
actionState = stateName;
actionUnlockTime = Time.time + minActionLock;
}
}
void TryAutoUnlockFromAction()
{
if (Time.time < actionUnlockTime) return;
var info = anim.GetCurrentAnimatorStateInfo(layerIndex);
if (!info.IsName(actionState))
{
inAction = false;
currentState = "";
return;
}
if (!info.loop && info.normalizedTime >= 0.99f && !anim.IsInTransition(layerIndex))
{
inAction = false;
currentState = "";
}
}
public void PlayAttack(int index = -1)
{
if (attackStates == null || attackStates.Length == 0) return;
if (index < 0) index = Random.Range(0, attackStates.Length);
index = Mathf.Clamp(index, 0, attackStates.Length - 1);
BeginAction(attackStates[index]);
}
public void PlayHit()
{
if (hitStates == null || hitStates.Length == 0) return;
BeginAction(hitStates[Random.Range(0, hitStates.Length)]);
}
public void PlayAnger()
{
if (!string.IsNullOrEmpty(angerState))
BeginAction(angerState);
}
public void PlayWalkBack(bool enable)
{
if (enable && !string.IsNullOrEmpty(walkBackState))
{
BeginAction(walkBackState);
}
}
public void PlayDeath()
{
if (!string.IsNullOrEmpty(deathState))
BeginAction(deathState);
}
public void OnActionFinished()
{
inAction = false;
currentState = "";
}
}