TIL (77) | 2023.11.14 | Enemy Attack State

kjg5370·2023년 11월 14일
0

TIL

목록 보기
75/91
post-thumbnail

들어가기 앞서

오늘은 기술면접을 하면서도 나왔던 상속을 이용하여 엘리트 몹의 여러가지 공격 상태를 구현해보았습니다.

오늘 배운 것

  • 상속
    기존에 정의된 클래스(부모 클래스 또는 상위 클래스)의 특성과 동작을 새로운 클래스(자식 클래스 또는 하위 클래스)가 물려받아 그대로 사용하거나 확장하여 새로운 클래스를 정의하는 것.

  • Attack State
    기본적인 AttackState를 하나 만듭니다.

    public class EnemyAttackState : EnemyBaseState
    {
        protected float lastShootTime;
        public EnemyAttackState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine)
        {
        }
    
        public override void Enter()
        {
            lastShootTime = 0f;
            base.Enter();
          StartAnimation(stateMachine.Enemy.AnimationData.AttackParameterHash);
        }
    
        public override void Exit()
        {
            base.Exit();
            StopAnimation(stateMachine.Enemy.AnimationData.AttackParameterHash);
        }
        public override void Update()
        {
            Rotate(GetTargetDirection());
        }
        private Vector3 GetTargetDirection()
        {
            Vector3 direction = stateMachine.Target.transform.position - stateMachine.Enemy.transform.position;
            return direction.normalized;
        }
    }

AttackState를 상속받을 모든 스테이트가 공통적으로 사용하는 lastShootTime을 protected 로 만들어 총알이 빠르게 발사되지 않도록 만들 계획입니다.

  • ProneAttackState
    오늘 만든 엎드려쏴 자세입니다.
    public class EnemyProneAttackState : EnemyAttackState
    {
        private EnemyGun weapon;
        private bool hasAdjustedRotation = false;
        public EnemyProneAttackState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine)
        {
            if (stateMachine.Enemy.Weapon != null)
            {
                weapon = stateMachine.Enemy.Weapon as EnemyGun;
            }
        }
        public override void Enter()
        {
            base.Enter();
            StartAnimation(stateMachine.Enemy.AnimationData.ProneAttackParameterHash);
            hasAdjustedRotation = false;
        }
    
        public override void Exit()
        {
            base.Exit();
            StopAnimation(stateMachine.Enemy.AnimationData.ProneAttackParameterHash);
            hasAdjustedRotation = false;
        }
        public override void Update()
        {
            base.Update();
            if (stateMachine.Enemy.EnemyHealth.PhaseIndex == 2)
            {
                stateMachine.ChangeState(stateMachine.MovePosState);
                return;
            }
    
            if (IsInAttackRange())
            {
                if (!hasAdjustedRotation)
                {
                    AdjustWeaponRotation(hitPoint);
                    hasAdjustedRotation = true;
                }
                if (Time.time - lastShootTime >= weapon.gunData.fireInterval)
                {
               
                    weapon.Shoot();
                    lastShootTime = Time.time;
                }
            }
        }
        private void AdjustWeaponRotation(Vector3 hitpoint)
        {
            // hitpoint를 향하는 방향으로 회전하는 쿼터니언 생성
            weapon.transform.rotation = Quaternion.LookRotation(hitpoint - weapon.transform.position);
        }
    }

엎드렸을 때 AttackRange안에 있다면 무기의 방향을 플레이어의 방향을 바라보도록 회전을 시키고 AttackState의 lastShootTime을 이용하여 fireInterval만큼의 시간동안 발사를 대기하도록 만들어줍니다.
stateMachine.Enemy.EnemyHealth.PhaseIndex를 이용해 다음 자세로 변경 시킵니다.

  • WalkCrouchingAttackState
    앉아서 걸으며 쏘는 자세입니다.
    public class EnemyWalkCrouchingAttackState : EnemyAttackState
    {
        private EnemyGun weapon;
        private bool hasAdjustedRotation = false;
        public EnemyWalkCrouchingAttackState(EnemyStateMachine ememyStateMachine) : base(ememyStateMachine)
        {
            if (stateMachine.Enemy.Weapon != null)
            {
                weapon = stateMachine.Enemy.Weapon as EnemyGun;
            }
        }
        public override void Enter()
        {
            base.Enter();
            stateMachine.MovementSpeedModifier = 0.4f;
         StartAnimation(stateMachine.Enemy.AnimationData.CrouchingAttackParameterHash);
            hasAdjustedRotation = false;
        }
    
        public override void Exit()
        {
            base.Exit();
         StopAnimation(stateMachine.Enemy.AnimationData.CrouchingAttackParameterHash);
            hasAdjustedRotation = false;
        }
        public override void Update()
        {
            base.Update();
            MoveLeftAndRight();
            if (IsInAttackRange())
            {
                if (!hasAdjustedRotation)
                {
                    AdjustWeaponRotation(hitPoint);
                    hasAdjustedRotation = true;
                }
                if (Time.time - lastShootTime >= weapon.gunData.fireInterval)
                {
                    weapon.Shoot();
                    lastShootTime = Time.time;
                }
            }
        }
        private void MoveLeftAndRight()
        {
            float direction = Mathf.Sin(Time.time); // 시간에 따라 좌우로 움직이도록 함
            Move(direction * stateMachine.Enemy.transform.right);
        }
        private void AdjustWeaponRotation(Vector3 hitpoint)
        {
            // hitpoint를 향하는 방향으로 회전하는 쿼터니언 생성
            weapon.transform.rotation = Quaternion.LookRotation(hitpoint - weapon.transform.position);
        }
    }

엎드려 쏴 자세와 같이 AdjustWeaponRotation을 이용하여 무기를 돌리고 MoveLeftAndRight함수에서 Mathf.Sin(Time.time);을 이용하여 시간에 따라 1에서 -1의 값을 받아와 stateMachine.Enemy.transform.right를 곱하여 캐릭터를 움직여줍니다. 이렇게 하면 캐릭터가 오른쪽과 왼쪽을 번갈아서 이동하게 됩니다.

진행 사항

  • 엘리트 몬스터 만들기
    • 체력이 높음
    • 체력이 특정 체력이하로 떨어지면 다음 페이즈로 변경
    • 적이 쏘는 레이에 플레이어가 맞으면 그 맞은 부분을 향해 무기가 회전
profile
학생입니다

1개의 댓글

comment-user-thumbnail
2023년 11월 14일

좋은 정보 감사합니다

답글 달기