unity-27: AI만들기
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);
}
}
댓글남기기