Chapter 7-1. AI : 동물 AI

Date:     Updated:

카테고리:

태그:

인프런에 있는 케이디님의 [유니티 3D] 실전! 생존게임 만들기 - Advanced 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

Chapter 7. 동물들의 공격형 AI, 도망형 AI 구현

🚖 돼지 3D 모델 설정

image

돼지 입장에서 보는 방향이 돼지 기준에서 앞 방향이어야 해서 z축이 돼지를 향해 있어야 하는데, 돼지 3 D 모델 pig 오브젝트는 z축이 돼지의 왼쪽에 있었다. 따라서 pig 오브젝트를 y 축으로 -90 도 회전시켜 주어 z축이 돼지가 바라보는 방향과 일치하게 해주었다. 돼지가 바라보는 방향이 돼지 기준의 앞 방향이어야 하므로.

image

돼지 3 D 모델 pig 오브젝트는 y 축으로 90도 회전되었으므로 나중에 회전 값에 연산을 하게 되면 이에 맞춰서 연산해야 하는 불편함이 따르게 된다. 따라서 부모 오브젝트로 원점 회전값(0, 0, 0)을 가진 Pig 빈 오브젝트를 만들었다. 실질적으로 돼지의 Mesh 를 가진 pig 오브젝트의 트랜스폼을 부모인 Pig 에서 관리하도록. 원점 회전값(0, 0, 0)을 가진 이 부모 Pig 오브젝트로 돼지의 이동, 회전 같은 트랜스폼을 대신 담당할 것이다.


컴포넌트 설정

  • Pig 👉 빈 오브젝트. 돼지의 트랜스폼, Collider 등을 대신 담당하게 될 것.
    • Box Collider - 돼지가 땅을 뚫고 떨어진다던지 관통된다던지 하지 않게 하기 위해
    • Rigidbody - 중력과 여러 물리적 영향을 바덱 하기 위해
      • 물리 현상에 의한 x, y, z 축 회전은 하지 않도록 Constraints 모두 체크해주었다.
    • pig 👉 실질적인 돼지 모습을 그리는 돼지 3 D 모델 오브젝트.
      • Animator - 돼지 애니메이션 담당
        • 돼지의 애니메이션은 돼지 Mesh 에서 이루어 지므로 이 pig 3 D 모델에 붙어야 한다.


돼지 애니메이션

image

돼지 3 D 모델에 내장되어 있던 애니메이션을 프레임 구간으로 잘라내어 애니메이션 State 들을 만듬

  • 파라미터로 인한 전이는 Has Exit Time 해제
  • Trigger 로 인해 시작됐던 State 가 끝나고 일어나는 전이는 Has Exit Time 체크


🚖 돼지 AI

📜Pig.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Pig : MonoBehaviour
{
    [SerializeField] private string animalName; // 동물의 이름
    [SerializeField] private int hp;  // 동물의 체력

    [SerializeField] private float walkSpeed;  // 걷기 속력

    private Vector3 direction;  // 방향

    // 상태 변수
    private bool isAction;  // 행동 중인지 아닌지 판별
    private bool isWalking; // 걷는지, 안 걷는지 판별

    [SerializeField] private float walkTime;  // 걷기 시간
    [SerializeField] private float waitTime;  // 대기 시간
    private float currentTime;

    // 필요한 컴포넌트
    [SerializeField] private Animator anim;
    [SerializeField] private Rigidbody rigidl;
    [SerializeField] private BoxCollider boxCol;

    void Start()
    {
        currentTime = waitTime;   // 대기 시작
        isAction = true;   // 대기도 행동
    }

    void Update()
    {
        Move();
        Rotation();
        ElapseTime();
    }

    private void Move()
    {
        if (isWalking)
            rigidl.MovePosition(transform.position + transform.forward * walkSpeed * Time.deltaTime);
    }

    private void Rotation()
    {
        if (isWalking)
        {
            Vector3 _rotation = Vector3.Lerp(transform.eulerAngles, direction, 0.01f);
            rigidl.MoveRotation(Quaternion.Euler(_rotation));
        }
    }

    private void ElapseTime()
    {
        if (isAction)
        {
            currentTime -= Time.deltaTime;
            if (currentTime <= 0)  // 랜덤하게 다음 행동을 개시
                ReSet();
        }
    }

    private void ReSet()  // 다음 행동 준비
    {
        isWalking = false;
        isAction = true;
        anim.SetBool("Walking", isWalking);

        direction.Set(0f, Random.Range(0f, 360f), 0f);

        RandomAction();
    }

    private void RandomAction()
    {
        int _random = Random.Range(0, 4); // 대기, 풀뜯기, 두리번, 걷기

        if (_random == 0)
            Wait();
        else if (_random == 1)
            Eat();
        else if (_random == 2)
            Peek();
        else if (_random == 3)
            TryWalk();
    }

    private void Wait()  // 대기
    {
        currentTime = waitTime;
        Debug.Log("대기");
    }

    private void Eat()  // 풀 뜯기
    {
        currentTime = waitTime;
        anim.SetTrigger("Eat");
        Debug.Log("풀 뜯기");
    }

    private void Peek()  // 두리번
    {
        currentTime = waitTime;
        anim.SetTrigger("Peek");
        Debug.Log("두리번");
    }

    private void TryWalk()  // 걷기
    {
        currentTime = walkTime;
        isWalking = true;
        anim.SetBool("Walking", isWalking);
        Debug.Log("걷기");
    }
}

돼지는 4 가지 행동(대기, 풀뜯기, 두리번, 걷기)을 랜덤하게 한다. 걷기는 walkTime 동안 실행되며, 그 외의 대기, 풀뜯기, 두리번은 waitTime 동안 행동이 실행 된다. 행동이 끝나면 다른 행동을 결정하고 실행한다.

  • 4 가지 상태 개시
    • Wait() 👉 대기
      • waitTime 동안 실행되므로 currentTimewaitTime 로 초기화
      • 디폴트 상태인 Idle 애니메이션 재생 됨
    • Eat() 👉 풀 뜯기
      • waitTime 동안 실행되므로 currentTimewaitTime 로 초기화
      • 먹기 애니메이션 재생
    • Peek() 👉 두리번
      • waitTime 동안 실행되므로 currentTimewaitTime 로 초기화
      • 두리번 거리는 애니메이션 재생
    • TryWalk() 👉 걷기
      • walkTime 동안 실행되므로 currentTimewalkTime 로 초기화
      • 걷는 애니메이션 재생
  • 돼지가 4 가지 행동 중 하나를 현재 행동하는 중이라면 isAction는 True다.
  • ElapseTime() 👉 행동 시간 카운트 다운
    • 돼지가 4 가지 행동 중 하나를 현재 행동하는 중이라면 매 프레임마다
      • currentTime을 1 초에 1 씩 감소시킨다. 이 시간 동안 행동을 한다.
        • 1 프레임당 Time.deltaTime 감소
      • currentTime가 0 에 도달했다면 다음 행동을 결정하고 실행해야 한다
        • ReSet()
  • ReSet() 👉 다음 행동 준비
    • 초기화
      • 정지 애니메이션으로 돌아감
      • isAction True
    • 랜덤하게 방향 설정
      • direction은 돼지가 향할 방향이다. y 축 360 도 회전값에서 랜덤하게 선택한다.
    • 랜덤하게 다음 행동 설정
      • RandomAction()
  • RandomAction() 👉 랜덤하게 다음 행동 결정
    • 0 ~ 3 중 랜덤하게 뽑아서 4 가지 행동 개시
  • 돼지가 걷기 상태라면
    • 매 프레임마다 돼지 이동시킴
      • 현재 위치로부터 돼지를 기준으로 한 앞 방향으로 1 초에 walkSpeed 크기 속도로.
    • 매 프레임마다 돼지 부드럽게 회전시킴
      • ReSet() 에서 설정했던 direction 방향으로 돼지를 회전 시킨다.
      • 현재 회전 값에서 direction 로 회전할 때까지 부드럽게 Lerp

image

  • 돼지는 5 초동안 걷고 난 후 다음 행동을 한다.
  • 돼지는 4 초동안 대기, 풀뜯기, 두리번 행동을 하고 난 후 다음 행동을 한다.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Unity Lesson 3 카테고리 내 다른 글 보러가기

댓글 남기기