protected IEnumerator ChaseTargetCoroutine()
{
currentChaseTime = 0;
while (currentChaseTime < ChaseTime)
{
Chase(theViewAngle.GetTargetPos()); //충분히 가까이 있고
if (Vector3.Distance(transform.position, theViewAngle.GetTargetPos()) <= 3f)
// 플레이어와 Creature 간의 거리가 3f 일 때
{
if (theViewAngle.View()) //바로 눈 앞에 있을 경우
{
Debug.Log("공격 시도!");
StartCoroutine(AttackCoroutine());
//바로 앞에 있을 때 공격 코루틴이 실행
}
}
yield return new WaitForSeconds(ChaseDelayTime);
currentChaseTime += ChaseDelayTime;
}
isChasing = false;
nav.ResetPath(); //추적이 끝난 Creature의 목표 좌표가 초기화된다.
}
protected IEnumerator AttackCoroutine()
{
isAttacking = true;
nav.ResetPath();
currentChaseTime = ChaseTime;
yield return new WaitForSeconds(0.5f); // 행동 변화 간의 딜레이 타임
transform.LookAt(theViewAngle.GetTargetPos()); // 플레이어를 바라보게 만든다.
anim.SetTrigger("Attack");
yield return new WaitForSeconds(0.5f);
RaycastHit _hit;
if (Physics.Raycast(transform.position + Vector3.up, transform.forward, out _hit, 3, targetMask))
{
thePlayerStatus.DecreaseHP(attackDamage);
Debug.Log("플레이어 적중!!");
}
else
{
Debug.Log("회피!!");
}
yield return new WaitForSeconds(attackDelay);
isAttacking = false;
StartCoroutine(ChaseTargetCoroutine());
}
public void Chase(Vector3 _targetPos)
{
isChasing = true;
destination = _targetPos;
// 목적지 변수를 생성하여 피해야 할 것이 아닌 쫓는 타겟으로 변경한다.
nav.speed = runSpeed;
isRunning = true;
anim.SetBool("Running", isRunning);
nav.SetDestination(destination);
Navigation AI
인게임에서 AI가 스스로 장애물과 진로를 파악하여 더 자연스러운 움직임을 보일 수 있도록하는 기능이다.
인스펙터창에서 Nav Mesh Agent 컴포넌트를 AI에 추가하여 적용 가능
Window -> Navigation 창을 통해 AI가 피해가야할 장애물, 범위 등을 따로 지정할 수 있다.
마지막으로 시야각 구현 스크립트에 Navigation을 적용시킬 함수를 생성한다.
private float CalcPathLength(Vector3 _targetPos)
{
NavMeshPath _path = new NavMeshPath();
nav.CalculatePath(_targetPos, _path);
Vector3[] _wayPoint = new Vector3[_path.corners.Length + 2];
//경로의 위치 및 길이 값이 담길 공간 배열 선언
_wayPoint[0] = transform.position;
_wayPoint[_path.corners.Length + 1] = _targetPos;
float _pathLength = 0;
for(int i = 0; i< _path.corners.Length; i++)
{ // AI가 스스로 공간 배열의 값을 순환하여 경로를 계산한다.
_wayPoint[i + 1] = _path.corners[i];
_pathLength += Vector3.Distance(_wayPoint[i], _wayPoint[i + 1]); // 경로 길이 계산
}
return _pathLength;
}
public class Gain : MonoBehaviour
{
// 충돌한 오브젝트tag가 Player이면 코인 삭제
// 즉, 플레이어가 코인을 먹는 것과 같은 표현이다.
private void OnTriggerEnter(Collider col)
{
if(col.gameObject.CompareTag("Player"))
{
Destroy(gameObject, 0f);
}
}
}
====================================================================
private void DropCoin()
{
Coin = (GameObject)Instantiate(Coin);
// 게임 오브젝트 코인 선언
Coin.transform.position = this.transform.position + new Vector3(0, 0.3f, 0); // AI가 쓰러진 그 자리에 코인이 나타난다.
}
-> 돼지를 죽이면 코인이 나오고 그 코인에 플레이어가 다가가면 사라지고 코인 카운트가 1 증가한다.
if (hitInfo.transform.tag == "NPC")
{
hitInfo.transform.GetComponent<Pig>().Damage(1, transform.position);
thepig.HP.SetActive(true);
} // 돼지를 공격할때만 Hp UI가 활성화(true)된다.
private void Dead()
{
PlaySE(sound_pig_Dead);
isWalking = false;
isRunning = false;
isDead = true;
anim.SetTrigger("Dead");
Destroy(gameObject, 3f); // 3초후 돼자 오브젝트 삭제
Invoke("DropCoin", 2); // 2초 딜레이후 DropCoin 함수 실행
}