enemy 상태 머신
enemy의 상태는 현재 총 4가지가 있으며
이 상태들은 EnemyBaseState를 기본적으로 상속받습니다. EnemyBaseState는 enemy의 이동이나 방향등의 함수를 가지고 있습니다.
EnemyIdleState
public class EnemyIdleState : EnemyBaseState { public EnemyIdleState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine) { } public override void Enter() { stateMachine.MovementSpeedModifier = 0f; base.Enter(); StartAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StartAnimation(stateMachine.Enemy.AnimationData.IdleParameterHash); } public override void Exit() { base.Exit(); StopAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StopAnimation(stateMachine.Enemy.AnimationData.IdleParameterHash); } public override void Update() { if (IsInChaseRange()) { stateMachine.ChangeState(stateMachine.ChasingState); return; } } }
EnemyIdleState는 주변에 아무것도 없이 기본적으로 움직이지 않는 상태 입니다. 만약 주변에 플레이어가 접근한다면 EnemyBaseState의 IsInChaseRange() 함수를 통해 플레이어를 추적하게 됩니다.
EnemyChasingState
public class EnemyChasingState : EnemyBaseState { public EnemyChasingState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine) { } public override void Enter() { stateMachine.MovementSpeedModifier = 1; base.Enter(); StartAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StartAnimation(stateMachine.Enemy.AnimationData.RunParameterHash); } public override void Exit() { base.Exit(); StopAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StopAnimation(stateMachine.Enemy.AnimationData.RunParameterHash); } public override void Update() { base.Update(); if (!IsInChaseRange()) { stateMachine.ChangeState(stateMachine.IdlingState); return; } else if (IsInAttackRange()) { stateMachine.ChangeState(stateMachine.AttackState); return; } else if (IsOutReturnRange()) { stateMachine.ChangeState(stateMachine.ReturnState); return; } } private bool IsInAttackRange() { // if (stateMachine.Target.IsDead) { return false; } float playerDistanceSqr = (stateMachine.Target.transform.position - stateMachine.Enemy.transform.position).sqrMagnitude; return playerDistanceSqr <= stateMachine.Enemy.Data.AttackRange * stateMachine.Enemy.Data.AttackRange; } private bool IsOutReturnRange() { float playerDistanceSqr = (stateMachine.Enemy.originalPosition.position - stateMachine.Enemy.transform.position).sqrMagnitude; return playerDistanceSqr >= stateMachine.Enemy.Data.ReturnDistance * stateMachine.Enemy.Data.ReturnDistance; } }
플레이어를 추적하는 중 공격 사거리에 들어오면 AttackState로 상태를 변경하고 원래 위치에서 특정 거리 이상을 추적하게 되면 원래 위치로 되돌아갑니다.
EnemyAttackState
public class EnemyAttackState : EnemyBaseState { public EnemyAttackState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine) { } public override void Enter() { stateMachine.MovementSpeedModifier = 0; base.Enter(); StartAnimation(stateMachine.Enemy.AnimationData.AttackParameterHash); StartAnimation(stateMachine.Enemy.AnimationData.BaseAttackParameterHash); } public override void Exit() { base.Exit(); StopAnimation(stateMachine.Enemy.AnimationData.AttackParameterHash); StopAnimation(stateMachine.Enemy.AnimationData.BaseAttackParameterHash); } public override void Update() { base.Update(); ForceMove(); float normalizedTime = GetNormalizedTime(stateMachine.Enemy.Animator, "Attack"); if (normalizedTime >= 1f) { if (IsInChaseRange()) { stateMachine.ChangeState(stateMachine.ChasingState); return; } else { stateMachine.ChangeState(stateMachine.IdlingState); return; } } } }
Attack 태그를 가진 애니메이션을 실행하고 플레이어가 다른 곳으로 이동을 하게 되면 다시 추적하거나 너무 멀어지면 기본 상태로 되돌아갑니다.
EnemyReturnState
public class EnemyReturnState : EnemyBaseState { public EnemyReturnState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine) { } public override void Enter() { stateMachine.MovementSpeedModifier = 1; base.Enter(); StartAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StartAnimation(stateMachine.Enemy.AnimationData.RunParameterHash); } public override void Exit() { base.Exit(); StopAnimation(stateMachine.Enemy.AnimationData.GroundParameterHash); StopAnimation(stateMachine.Enemy.AnimationData.RunParameterHash); } public override void Update() { if(!IsInReturnPosition()) { ReturnToOriginalPosition(); return; }else { stateMachine.ChangeState(stateMachine.IdlingState); return; } } private bool IsInReturnPosition() { float playerDistanceSqr = (stateMachine.Enemy.originalPosition.position - stateMachine.Enemy.transform.position).sqrMagnitude; return playerDistanceSqr <= 0.1; } }
enemy가 추적 도중 원래 위치에서 너무 멀어졌을 때 다시 원래 위치로 되돌아가는 상태입니다.