Unity

[TIL] Unity 최종프로젝트 몬스터 트러블 슈팅

unihee1 2025. 4. 24. 20:33

2025.04.22 - [Unity] - [TIL] Unity 최종프로젝트 몬스터 애니메이션 트러블 슈팅

 

[TIL] Unity 최종프로젝트 몬스터 애니메이션 트러블 슈팅

2025.04.21 - [Unity] - [TIL] Unity 최종프로젝트 몬스터 애니메이션(Animation Event) [TIL] Unity 최종프로젝트 몬스터 애니메이션(Animation Event)2025.04.16 - [Unity] - [TIL] Unity 최종프로젝트 몬스터 HP바 만들기 [TIL]

unihee1.tistory.com

 

1. 발단

위의 영상과 같이 몬스터가 Wander 상태일 때 다가가면 소리지는 애니메이션이 재생되면서 움직이는 것을 볼 수 있다.

Wander 상태에서 다가가면 그자리에 멈추고 소리지는 애니메이션이 재생되도록 수정해야 한다.

 

2. 전개, 절정

전과 같은 애니메이터의 문제인가 한 번 살펴보았다. 하지만 애니메이션은 잘 전환되고 있었다.

그렇다면 Wander상태 스크립트의 문제인지 살펴보았다.

- WanderState 스트립트

using UnityEngine;

public class WanderState : IState
{
    [SerializeField] private MonsterController monster;
    [SerializeField] private StateMachine stateMachine;
    private float wanderTime = 10f;
    private float timer;

    private bool movingRight = true;
    private Vector3 startPos;
    public WanderState(MonsterController monster, StateMachine stateMachine)
    {
        this.monster = monster;
        this.stateMachine = stateMachine;
    }
    public void Enter()
    {
        startPos = monster.transform.position;
        monster.animator.SetBool("isWander", true);
        timer = 0f;
    }
    public void Update()
    {
        timer += Time.deltaTime;
        float distanceToTarget = Vector3.Distance(monster.transform.position, monster.target.position);

        if (distanceToTarget < monster.Data.monsterAttackRange)
        {
            stateMachine.ChangeState(new AttackState(monster, stateMachine));
        }
        else if (distanceToTarget < monster.Data.monsterDetectRange)
        {
            Vector3 direction = (monster.target.position - monster.transform.position).normalized;
            direction.y = 0f; 

            if (direction != Vector3.zero)
            {
                monster.transform.rotation = Quaternion.LookRotation(direction);
            }
            monster.animator.SetBool("isScream", true);
        }
        else if (timer > wanderTime)
        {
            stateMachine.ChangeState(new IdleState(monster, stateMachine));
        }

        Wandering();
        
    }
    public void Exit()
    {
        monster.animator.SetBool("isWander", false);
    }

    private void Wandering()
    {

        float walkSpeed = monster.Data.monsterWalkSpeed;
        Vector3 moveDir = movingRight ? Vector3.right : Vector3.left;
        monster.transform.position += moveDir * walkSpeed * Time.deltaTime;
        monster.transform.LookAt(monster.transform.position + moveDir);

        float offset = monster.transform.position.x - startPos.x;
        if (movingRight && offset >= monster.Data.wanderRadius)
            movingRight = false;
        else if (!movingRight && offset <= -monster.Data.wanderRadius)
            movingRight = true;
    }


}

Wander 상태에 진입하게 되면 걷는 애니메이션이 재생되고 Update에서 distanceToTarget와  AttackRange, DetectRange를 비교하여 각각에 해당하는 범위에 들어오게 되면 다음 상태 전환하고 Wandering 함수는 몬스터가 일정 영역을 왔다갔다 움직이도록 구현되어 있다. 여기서 문제가 생긴 것이다. 

 else if (distanceToTarget < monster.Data.monsterDetectRange)에서 참이면 소리지르는 애니메이션이 재생되게 되어 있는데 Chase상태로 전환되는 시기가 애니메이션이 종료되면 전환되기 때문에 소리지르는 애니메이션이 재생되는 동안에는 Wanderring함수도 함께 실행된다.

그렇다면 소리지르는 애니메이션이 재생되는 동안에 Wandering 함수가 실행되지 않도록 수정해야 한다.

 

3. 결말, 마무리

소리 지르는 애니메이션이 재생되는 동안 Wandering 함수가 실행되지 않도록 하기 위해 Wandering함수 내부에 코드를 추가해주었다.

 AnimatorStateInfo stateInfo = monster.animator.GetCurrentAnimatorStateInfo(0);
 bool isScreaming = stateInfo.IsName("Zombie Scream");

 if (isScreaming)
 {
     return;
 }

 Wandering 함수가 호출되면 지금 실행되는 animation Clip이 무엇인지 가져온다.

bool 변수인 isScreaming에 animation Clip이름이 Zombie Scream이 맞는지 확인한 다음  맞으면 true, 아니면 false를 저장한다.  그런 다음 if문을 통해 isScreaming 참이면 Wandering함수가 더이상 실행되지 않도록 한다.

코드를 추가하고 실행하면 영상과 같이 소리지르는 애니메이션이 재생될 때 자리에 멈춰있는 것을 볼 수 있다.