본문 바로가기
UNITY/Unity Study

유니티(Unity) - 플레이어 따라다니는 npc 만들기

by GREEN나무 2023. 8. 3.
728x90

◈ 플레이어 따라다니는 NPC 만들기

 

바닥과 플레이어,  npc 객체 만들기

 

플레이어,  npc 객체에 Rigidbody 컴포넌트 추가하기

윈도우 > PackageManager > Packages:  Unity Registry > AI Navigation 설치

 

NPC에 Rigidbody 컴포넌트와 Nav Mash Agent 컴포넌트 추가

 

 

NPC.cs 를 npc 오브젝트에 추가

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

public class NPC : MonoBehaviour
{
    public LayerMask whatIsTarget;
    private Transform targetTransform; // 대상의 Transform
    private NavMeshAgent navMeshAgent;
    public float detectionRange = 10.0f; // 검출 가능한 최대 거리

    private bool hasTarget
    {
        get { return targetTransform != null; }
    }

    private void Awake()
    {
        // 컴포넌트 초기화
        navMeshAgent = GetComponent<NavMeshAgent>();
        navMeshAgent.enabled = true; // NavMeshAgent를 활성화
    }

    private void Start()
    {
        // AI의 추적 루틴 시작
        StartCoroutine(UpdatePath());
    }

    private void Update()
    {
        // 추적 대상의 존재 여부에 따라 다른 애니메이션 재생
        // zombieAnimator.SetBool("HasTarget", hasTarget);
    }

    private IEnumerator UpdatePath()
    {
        // 살아 있는 동안 무한 루프
        while (true) // !dead)
        {
            // 추적 대상의 위치 갱신
            UpdateTarget();

            // 0.25초 주기로 처리 반복
            yield return new WaitForSeconds(0.25f);
        }
    }

    private void UpdateTarget()
    {
        Collider[] colliders = Physics.OverlapSphere(transform.position, detectionRange, whatIsTarget);
        if (colliders.Length > 0)
        {
            float closestDistance = Mathf.Infinity;
            Transform closestTarget = null;

            foreach (Collider collider in colliders)
            {
                float distanceToTarget = Vector3.Distance(transform.position, collider.transform.position);
                if (distanceToTarget < closestDistance)
                {
                    closestDistance = distanceToTarget;
                    closestTarget = collider.transform;
                }
            }

            if (closestTarget != null)
            {
                targetTransform = closestTarget;
                navMeshAgent.SetDestination(targetTransform.position);
            }
        }
        else
        {
            targetTransform = null;
            navMeshAgent.ResetPath(); // 대상이 없을 때 경로 초기화
        }
    }
}

 

Inspector > Lqyer > ▽ 눌러서 Add Layer > Player 추가

 

NPC로 돌아와서  NPC 스크립트 컴포넌트의 What Is Target을 Player로 바꾸기

Player의 레이어를 Player로 바꾸기

PlayerMove.cs를 Player 오브젝트에 추가

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

public class PlayerMovement : MonoBehaviour
{
    public float moveSpeed = 5.0f;

    private Rigidbody playerRigidbody;

    private void Awake()
    {
        playerRigidbody = GetComponent<Rigidbody>();
    }

    private void Update()
    {
        // 플레이어 입력 처리
        float horizontalInput = Input.GetAxis("Horizontal");
        float verticalInput = Input.GetAxis("Vertical");

        // 이동 방향 계산
        Vector3 movement = new Vector3(horizontalInput, 0.0f, verticalInput) * moveSpeed * Time.deltaTime;

        // Rigidbody를 이용해 플레이어 이동
        playerRigidbody.MovePosition(transform.position + movement);
    }
}

 

재생했더니 

오류가 뜨네요.

네비게이션 영역을 지정하지 않아서 그래요.

네비게이션 영역 설정

Window > AI > Navigation(Obsolete)



하이라키의 Plan을 선택하고

내비게이션 뷰 > Object > Navigation Static을 체크

Navigation Static을 체크하면 해당 메시를 캐릭터가 길을 찾을 수 있는 표면으로 설정됩니다.

 

Bake 탭 

Bake 버튼을 누르면 씬 뷰에서 Plane 위에 파란색 영역이 생깁니다.

이게 캐릭터가 길을 찾아서 이동할 수 있는 영역을 의미하는 NavMesh입니다.

(Bake는 빵이나 과자같은 것을 굽는다는 의미로 이렇게 NavMesh를 만드는 작업 역시 "NavMesh를 굽는다"라고 표현합니다.)

 

재생해보겠습니다.

플레이어(노랑)가 NPC 주변으로 가면 NPC가 따라오는걸 볼 수 있습니다.

https://youtu.be/2DM3M4FORYA