본문 바로가기
공부/Unity 기초

3D FPS - 14 / 애니메이션 상태 설계

by svcbn 2022. 5. 25.

애니메이터에 애니메이션을 추가하고

트리거를 추가, transition을 설정해준다.

 

 

 

 

 

 

Animation창에서 Event 추가

 

 

 

 

 

 

 

EnemyAnimation 스크립트를 enemy에 연결

public Enemy enemy;

    public void OnEventAttack()
    {
        enemy.OnEventAttack();
    }

 

 

 

 

 

 

enemy에서 OnEventAttack 함수를 만들어 기존의 Attack 상태로 전이하던것을 함수 호출식으로 변경

internal void OnEventAttack()
    {
        // 공격 행위
        // 나와 target의 거리를 구해서
        float distance = Vector3.Distance(transform.position, target.transform.position);

        // 만약 그 거리가 공격거리보다 크다면
        if (distance > attackDistance)
        {
            // Move상태로 전이하고싶다.
            state = State.Move;
            anim.SetTrigger("Move");
            agent.isStopped = false;

        }

        // 공격 성공
        else
        {
            // 플레이어를 공격하고
            php.AddDamage();

            // HitManager의 Hit함수를 호출하고싶다.
            HitManager.instance.Hit();

        }

 

 

 

 

Enemy 전문

더보기
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

// FSM으로 상태를 제어하고싶다.
// 정지, 이동, 공격, 죽음
public class Enemy : MonoBehaviour
{

    public float speed = 1;
    public float findDistance = 5;
    public float attackDistance = 1.5f;

    

    public float traceDistance = 15;
    public float sightDegree = 45;
    
    public enum State
    {
        Idle,
        Move,
        Attack,
        Die,
        Return
    }

    // Animator > Animation Controller > Animation Clips
    public Animator anim;


    NavMeshAgent agent;
    public State state;
    PlayerHP php;

    GameObject target;

    Vector3 originPosition;

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        
        state = State.Idle;

        target = GameObject.Find("Player");

        php = target.GetComponent<PlayerHP>();

        // 최초 위치를 originPosition 변수에 저장한다.
        originPosition = transform.position;


    }

    // Update is called once per frame
    void Update()
    {
        if (state == State.Idle)
        {
            UpdateIdle();
        }

        else if (state == State.Move)
        {
            UpdateMove();
        }

        else if (state == State.Return)
        {
            UpdateReturn();
        }
    }

    
    private void UpdateIdle()
    {
        // 나와 target의 거리를 구해서
        float distance = Vector3.Distance(transform.position, target.transform.position);

        bool isInSight = CheckPlayerAngle(target.transform.position);

        // 만약 그 거리가 감지거리보다 작으면
        if (distance < findDistance && isInSight)
        {
            // Move상태로 전이하고싶다.
            state = State.Move;
            anim.SetTrigger("Move");

            agent.destination = target.transform.position;

        }

    }

    bool CheckPlayerAngle(Vector3 position)
    {
        // 체크하려는 대상을 바라보는 벡터를 구한다.
        Vector3 direction = position - transform.position;

        // 나의 정면 벡터와 앞에서 구한 벡터를 비교해서 사잇각을 구한다.
        float checkDegree = Vector3.Angle(transform.forward, direction);

        // 구해진 각도가 45도 이내라면 true, 45도 밖이면 false라고 반환한다.
        if (checkDegree <= sightDegree)
        {
            return true;
        }
        else
        {
            return false;
        }

    }

    
    private void UpdateMove()
    {
        // 현재 위치가 최대 추적 가능 거리를 넘어갔는지 여부를 판단한다.
        float trace = Vector3.Distance(originPosition, transform.position);

        // 만일, 최대 추적 가능 거리를 넘어갔다면 상태를 복귀 상태로 전환한다.
        if (trace > traceDistance)
        {
            state = State.Return;
        }


        // target방향으로 이동하다가
        //Vector3 dir = target.transform.position - transform.position;
        //dir.Normalize();
        //transform.position += dir * speed * Time.deltaTime;
        agent.destination = target.transform.position;

        // 나와 target의 거리를 구해서
        float distance = Vector3.Distance(transform.position, target.transform.position);

        // 만약 그 거리가 공격거리보다 작으면
        if (distance < attackDistance)
        {
            // Attack으로 전이하고싶다.
            state = State.Attack;
            anim.SetTrigger("Attack");
            agent.isStopped = true;
        }


    }

    internal void OnEventAttack()
    {
        // 공격 행위
        // 나와 target의 거리를 구해서
        float distance = Vector3.Distance(transform.position, target.transform.position);

        // 만약 그 거리가 공격거리보다 크다면
        if (distance > attackDistance)
        {
            // Move상태로 전이하고싶다.
            state = State.Move;
            anim.SetTrigger("Move");
            agent.isStopped = false;

        }

        // 공격 성공
        else
        {
            // 플레이어를 공격하고
            php.AddDamage();

            // HitManager의 Hit함수를 호출하고싶다.
            HitManager.instance.Hit();

        }

    }
    

    
    public void AddDamage (int damage)
    {
        agent.isStopped = true;
        state = State.Die;
        anim.SetTrigger("Die");

        Destroy(gameObject, 3);

    }

    private void OnDestroy()
    {
        EnemyManager.instance.COUNT--;
    }

    void UpdateReturn()
    {
        // 만일, 나의 현재 위치가 originPosition 위치에서 10센티미터 이상이라면
        Vector3 dir = originPosition - transform.position;

        if (dir.magnitude > 0.1f)
        {
            // originPosition 방향으로 이동한다.
            transform.position += dir.normalized * speed * Time.deltaTime;
        }


        // 그렇지 않다면, 나의 위치를 originPosition으로 설정한다.
        else
        {
            transform.position = originPosition;

            // 상태를 다시 대기 상태로 전환한다.
            state = State.Idle;

        }

        // 나와 target의 거리를 구해서
        //float distance = Vector3.Distance(transform.position, target.transform.position);

        // 복귀 중 감지거리 안으로 Player가 들어오면
        //if (distance < findDistance)
        {
            // 상태를 Move 상태로 전이한다.
            //state = State.Move;
        }

        
    }
}

'공부 > Unity 기초' 카테고리의 다른 글

3D 그래픽 - 1 / Material  (0) 2022.05.27
3D FPS - 15 / 애니메이션 순환  (0) 2022.05.26
3D FPS - 13 / 사다리 이동  (0) 2022.05.24
3D FPS - 12 / 모델링 적용  (0) 2022.05.23
3D FPS - 11 / 적 시야각  (0) 2022.05.23