1 분 소요

AI만들기

  • 적, Ai의 입장에서 생각하기
  • 네모 영역안에서만 움직이게 하기(평화 시)
  • AI는 기본적으로 한 명령이 내려지면 그 명령을 수행하기 전엔 다른 명령을 받지 않도록 만든다.
  • 목적지에 도착했을때까지 다른 명령 듣지 않다가, 목적지에 도착하면 다음 명령을 따름

  • postarget과 transform.position의 내부는 int로 되어있음.
  • float는 실수이고, 지수임. 지수는 정확히 1,2가아니라 1에수렴(근사값), 2에수렴한 값임.
  • 따라서 float끼리는 == 연산을 하면 안됨
  • Vector3.Distance(a,b) < 0.1f 로 해결!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class ZombieController : MonoBehaviour
{
    public enum eActionState
    {
        IDLE              =0,
        WALK,
        RUN,
        ATTACK,
        HIT,
    }
    [SerializeField] float _limitX = 5;
    [SerializeField] float _limitZ = 5;
    [SerializeField] float _moveSpeed;   //뛰는 스피드
    [SerializeField] float _walkSpeed;  //걷는 스피드
    [SerializeField] BoxCollider _damageZone;
    eActionState _stateAction;
    Animator _ctrlAni;
    Vector3 _posTarget;
    float _Speed;       //최종 스피드
    bool _isDeath;   //플래그 (키고 끄고 할수있는 작용 
    bool _isAttack;
    NavMeshAgent _navAgent;
    Vector3 _startPos;          //cube상에서의 중심 위치 = center
    

    private void Awake()
    {
        _isDeath = false;   //초기화
        _isAttack = false;  //초기화
       _ctrlAni = GetComponent<Animator>();
        _navAgent = GetComponent<NavMeshAgent>();   // 좀비에 있는 navmeshagent를 가져옴
        _startPos = _posTarget = transform.position; //최초위치(transform.postion)가 startPos임
    }
    
    void Start()
    {
    }

    private void Update()
    {
        if (_isDeath)     //죽으면 아무것도 못하게 함
            return;

        if(Vector3.Distance(_posTarget,transform.position) <= 0.1f)  // postraget과 transposition과의 거리가 0.1보다 작을때 (거의 값이 같을때) 다음명령 시작
        {                                                            
            ChangedAction(eActionState.WALK);       //액션을 walk로 바꿈
            _posTarget= GetRandomPos(_startPos, _limitX, _limitZ);   // 목표위치(postarget)는 limitX와 limitZ의 벡터값과 center값(centerPos)이 더해져야함
            _navAgent.destination = _posTarget;         //navagent의 목표값이 목표위치(postarget)
        }
    }


    Vector3 GetRandomPos(Vector3 center, float limitX, float limitZ)     //좀비가 움직일 임의의 위치를 반환
    {
         float rX = Random.Range(-limitX, limitX);      //센터를 중심으로 -5, +5 사이에서 x좌표 랜덤값
         float rZ = Random.Range(-limitZ, limitZ);      //센터를 중심으로 -5, +5 사이에서 z좌표 랜덤값

        Vector3 rv = new Vector3(rX,0,rZ);
        return center+ rv;      //center가 있어야 cube에서의 중심점에서 x,z에 따라 움직임
    }
    
    
    void ChangedAction(eActionState state)
    {

        switch (state)                    //애니메이션이 바뀌는 곳에서 속도를 변경 해주는게 직관적임
        {
            case eActionState.WALK:         //walk일때 최종스피드에다가 워크스피드를 넣어줌
                if (_stateAction != eActionState.ATTACK)
                {
                    _navAgent.speed = _walkSpeed;
                    _ctrlAni.SetInteger("AniState", (int)_stateAction);
                    _stateAction = state;
                }
                break;
            case eActionState.RUN:
                _navAgent.speed = _moveSpeed;
                _ctrlAni.SetInteger("AniState", (int)_stateAction);
                _stateAction = state;
                break;
            case eActionState.ATTACK:       //모든것이 변하는 곳에 공격할때는 isAttack을 킴
                if (_stateAction == eActionState.RUN)
                {
                    _isAttack = true;
                    _ctrlAni.SetInteger("AniState", (int)_stateAction);
                    _stateAction = state;

                }
                break;
            case eActionState.HIT:      //맞으면 isDeath를 킴
                _isDeath = true;
                _ctrlAni.SetInteger("AniState", (int)_stateAction);
                _stateAction = state;
                break;
            case eActionState.IDLE:
                _ctrlAni.SetInteger("AniState", (int)_stateAction);
                _stateAction = state;
                break;

        }

        _stateAction = state;
        _ctrlAni.SetInteger("AniState", (int)_stateAction);
    }
}    
    

댓글남기기