Unity

그랩팩 개발 일지 6

psb08 2025. 2. 12. 21:20
728x90

개발을 하다가 NavMesh라는 것을 알게 되어서 NavMesh를 조금 공부하고

적 코드를 바꾸었습니다.

 

NightMareEnemy.cs

using DG.Tweening;
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

public class NightMareEnemy : MonoBehaviour
{
    [SerializeField] private Transform player;
    [SerializeField] private MonoBehaviour mouseLookScript;
    [SerializeField] private NavMeshAgent agent;
    [SerializeField] private float stopDistance = 2f;
    [SerializeField] private float bulletDetectionRange = 3f;
    [SerializeField] private float retreatDistance = 1.5f; // 총에 맞았을 때 뒤로 가는 거리
    [SerializeField] private float retreatDuration = 0.3f; // 후퇴 시간

    private bool isCutsceneActive = false;

    private bool isRetreating = false;

    private void Start()
    {
        if (agent == null)
            agent = GetComponent<NavMeshAgent>(); // NavMeshAgent 가져오기
    }

    void Update()
    {
        transform.position = new Vector3(transform.position.x, 0.5f, transform.position.z);

        if (player == null || isCutsceneActive || isRetreating) return;

        DetectNearbyBullets();

        float distanceToPlayer = Vector3.Distance(transform.position, player.position);

        if (distanceToPlayer > stopDistance)
        {
            agent.SetDestination(player.position);
        }
        else
        {
            // 적이 일정 거리 안으로 들어오면 컷신 실행
            StartCoroutine(KillPlayerCutscene());
        }
    }

    private void DetectNearbyBullets()
    {
        Collider[] hitColliders = Physics.OverlapSphere(transform.position, bulletDetectionRange); // 범위 내 오브젝트 감지

        foreach (Collider hitCollider in hitColliders)
        {
            if (hitCollider.CompareTag("Bullet")) // 감지된 오브젝트가 총알인지 확인
            {
                RetreatFromPlayer(); // 후퇴 실행
                break; // 한 번 감지하면 더 이상 확인할 필요 없음
            }
        }
    }

    private void RetreatFromPlayer()
    {
        if (player == null) return;

        isRetreating = true; // 후퇴 상태 활성화

        // 플레이어 반대 방향으로 이동
        Vector3 retreatDirection = (transform.position - player.position).normalized;
        Vector3 retreatPosition = transform.position + retreatDirection * retreatDistance;

        // Y축 이동을 완전히 막기 위해 Y값을 유지한 상태로 새로운 벡터 생성
        retreatPosition = new Vector3(retreatPosition.x, transform.position.y, retreatPosition.z);

        // DOTween을 사용해 XZ 좌표만 이동 (Y값은 그대로 유지)
        transform.DOMoveX(retreatPosition.x, retreatDuration);
        transform.DOMoveZ(retreatPosition.z, retreatDuration).OnComplete(() =>
        {
            isRetreating = false; // 후퇴 완료 후 다시 움직일 수 있도록 설정
        });
    }


    private IEnumerator KillPlayerCutscene()
    {
        isCutsceneActive = true; // 컷신 활성화

        // 1. 플레이어 조작 비활성화
        if (player.GetComponent<CharacterController>())
            player.GetComponent<CharacterController>().enabled = false;
        if (mouseLookScript != null) mouseLookScript.enabled = false;

        Cursor.lockState = CursorLockMode.None;
        Cursor.visible = true;
 
        Vector3 targetPosition = transform.position - transform.forward * -3f; // 적의 위치 근처로 카메라 이동
        Camera.main.transform.DOMove(targetPosition, 0.1f); // 카메라 이동

        // 카메라가 적을 바라보도록 회전
        Camera.main.transform.DOLookAt(transform.position, 0.3f);

        yield return new WaitForSeconds(0.3f); // 카메라 이동과 회전하는 시간

        // 3. 적을 흔들기
        transform.DOShakePosition(1.5f, 0.2f, 10, 90, false, true);

        yield return new WaitForSeconds(1.5f); // 적이 흔들리는 시간

        // 3. 플레이어 제거
        SceneManager.LoadScene("GameOver");
    }


}

NavMeshAgent를 가져오고 총알이 일정 거리에 들어오면 후퇴합니다.

그리고 컷신을 카메라가 적 쪽으로 이동하도록 코드를 수정했습니다.

 

NavMesh로 벽을 만들고 벽이 있으면 적이 돌아옵니다.

 

그리고 주황색 손에 총알을 발사하는 코드에 쿨타임을 추가했습니다.

그리고 UI로 손에 띄우도록 했습니다.

 

OrangeHand.cs

using TMPro;
using UnityEngine;

public class OrangeHand : MonoBehaviour
{
    //주황 손, 마우스 오른쪽 클릭 시 총알 발사
    [SerializeField] private TextMeshProUGUI text;
    public GameObject bulletPrefab;
    public Transform bulletSpawnPoint;
    public float bulletSpeed = 20f;
    public float fireCooldown = 3f; //3초 쿨타임 추가

    private float lastFireTime = -3f; //게임 시작 시 바로 발사 가능하도록 설정
    private void Update()
    {
        if (Input.GetMouseButtonDown(1) && Time.time >= lastFireTime + fireCooldown)
        {
            FireBullet();
            lastFireTime = Time.time; //마지막 발사 시간을 현재 시간으로 갱신
        }

        UpdateCooldownText();
    }

    private void FireBullet()
    {
        GameObject bullet = Instantiate(bulletPrefab, bulletSpawnPoint.position, bulletPrefab.transform.rotation);
        Rigidbody rb = bullet.GetComponent<Rigidbody>();
        rb.velocity = bulletSpawnPoint.forward * bulletSpeed;
    }

    private void UpdateCooldownText()
    {
        float remainingTime = Mathf.Max(0, lastFireTime + fireCooldown - Time.time);
        text.text = ""+remainingTime.ToString("F1") + "s";
    }
}

 

쿨타임을 UI에 띄우도록 수정했습니다.

 

 

 

+ 컷신이 나오면 손 오브젝트를 제거하도록 만들었습니다.

728x90

'Unity' 카테고리의 다른 글

그랩팩 개발 일지 8  (0) 2025.02.14
그랩팩 개발 일지 7  (1) 2025.02.13
그랩팩 개발 일지 5  (0) 2025.02.11
그랩팩 개발 일지 4  (0) 2025.02.10
그랩팩 개발 일지 3  (0) 2025.02.09