Unity Chapter 11-20. 좀비 TPS 게임 만들기 : Player Controller

Date:     Updated:

카테고리:

태그:

인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!


Chapter 11. 좀비 TPS 게임 만들기

📜PlayerController.cs

Player Character 오브젝트에 붙여준다.

각각 독자적으로 동작하는 Player Character의 많은 컴포넌트들을 총괄 관리해주는 역할을 함.

  1. 플레이어가 죽었을 때
    • 플레이어가 리스폰 될 수 있도록 함
    • 또한 플레이어가 죽었을 때 활성화 되거나 비활성화 되는 Player Character의 컴포넌트들을 통제
  2. 아이템과 충돌 처리가 일어나면 플레이어가 아이템을 먹을 수 있도록 함
    • 아이템 먹는 애니메이션 재생
    • 아이템 먹을때 오디오 재생
using UnityEngine;
using UnityEngine.AI;

public class PlayerController : MonoBehaviour
{
    private Animator animator;
    public AudioClip itemPickupClip;
    public int lifeRemains = 3;
    private AudioSource playerAudioPlayer;
    private PlayerHealth playerHealth;
    private PlayerMovement playerMovement;
    private PlayerShooter playerShooter;

    // Start is called before the first frame update
    private void Start()
    {
        playerMovement = GetComponent<PlayerMovement>();
        playerShooter = GetComponent<PlayerShooter>();
        playerHealth = GetComponent<PlayerHealth>();
        playerAudioPlayer = GetComponent<AudioSource>();
        playerHealth.OnDeath += HandleDeath;

        UIManager.Instance.UpdateLifeText(lifeRemains);
        Cursor.visible = false;

    }

    private void HandleDeath()
    {
        playerMovement.enabled = false;
        playerShooter.enabled = false;

        if (lifeRemains > 0)
        {
            lifeRemains--;
            UIManager.Instance.UpdateLifeText(lifeRemains);
            Invoke("Respawn", 3f);
        }
        else
        {
            GameManager.Instance.EndGame();
        }

        Cursor.visible = true;
    }

    public void Respawn()
    {
        gameObject.SetActive(false);
        transform.position = Utility.GetRandomPointOnNavMesh(transform.position, 30f, NavMesh.AllAreas);

        gameObject.SetActive(true);
        playerMovement.enabled = true;
        playerShooter.enabled = true;

        playerShooter.gun.ammoRemain = 120;

        Cursor.visible = false;
    }


    private void OnTriggerEnter(Collider other)
    {
        // 아이템과 충돌한 경우 해당 아이템을 사용하는 처리
        // 사망하지 않은 경우에만 아이템 사용가능
        if (!playerHealth.dead)
        {
            // 충돌한 상대방으로 부터 Item 컴포넌트를 가져오기 시도
            var item = other.GetComponent<IItem>();

            // 충돌한 상대방으로부터 Item 컴포넌트가 가져오는데 성공했다면
            if (item != null)
            {
                // Use 메서드를 실행하여 아이템 사용
                item.Use(gameObject);
                // 아이템 습득 소리 재생
                playerAudioPlayer.PlayOneShot(itemPickupClip);
            }
        }
    }
}

멤버 변수

    private Animator animator;
    public AudioClip itemPickupClip;
    public int lifeRemains = 3;
    private AudioSource playerAudioPlayer;
    private PlayerHealth playerHealth;
    private PlayerMovement playerMovement;
    private PlayerShooter playerShooter;
  • animator
    • 아이템을 먹을 때 애니메이션 처리를 하기 위해
  • itemPickupClip
    • 아이템을 먹을 때 재생할 오디오 클립
  • lifeRemains
    • 남은 생명 수
    • 초기 값 3 에서 시작
  • playerAudioPlayer
    • 아이템 먹을 때 오디오 클립을 재생할 오디오 재생기
  • Player Character 오브젝트에 붙어있는 다른 스크립트들을 일괄적으로 제어하기 위해
    • playerHealth 👉📜PlayerHealth.cs
    • playerMovement 👉📜PlayerMovement.cs
    • playerShooter 👉📜PlayerShooter.cs


멤버 함수

private void Start()

    private void Start()
    {
        playerMovement = GetComponent<PlayerMovement>();
        playerShooter = GetComponent<PlayerShooter>();
        playerHealth = GetComponent<PlayerHealth>();
        playerAudioPlayer = GetComponent<AudioSource>();

        playerHealth.OnDeath += HandleDeath;

        UIManager.Instance.UpdateLifeText(lifeRemains);
        Cursor.visible = false;
    }
  • 컴포넌트들 가져오기
  • 플레이어가 사망하면 HandleDeath() 함수를 실행하도록 한다.
    • 📜PlayerHealth.cs가 📜LivingEntity.cs로부터 상속 받아 가지고 있는 OnDeath 아밴트private void HandleDeath() 함수를 추가로 등록해준다.
      • OnDeath 아밴트 👉 📜LivingEntity.cs의 Action 타입의 이벤트 멤버로 생명체가 사망하면 실행할 함수들이 등록된다.
  • 남은 목숨의 수 UI 갱신
    • UIManager.Instance.UpdateLifeText(lifeRemains);
  • 마우스 커서 비활성화
    • 플레이어가 살아있는 동안에는 마우스 커서가 보이지 않도록.
    • Cursor.visible = false


private void HandleDeath()

플레이어가 사망할 때 처리

    private void HandleDeath()
    {
        playerMovement.enabled = false;
        playerShooter.enabled = false;

        if (lifeRemains > 0)
        {
            lifeRemains--;
            UIManager.Instance.UpdateLifeText(lifeRemains);
            Invoke("Respawn", 3f);
        }
        else
        {
            GameManager.Instance.EndGame();
        }

        Cursor.visible = true;
    }
  • 플레이어가 사망 상태가 되면 특정 컴포넌트들 비활성화
    • 플레이어가 이동하지 못하도록 📜PlayerMovement.cs 를 비활성화 해야하고
      • playerMovement.enabled = false;
    • 플레이어가 총을 쏘지 못하도록 📜PlayerShooter.cs 를 비활성화 해야한다.
      • playerShooter.enabled = false;
  • 사망 했어도 아직 목숨이 남아 있다면 if (lifeRemains > 0)
    • lifeRemains 1 감소
    • 남은 목숨의 수 UI 갱신
    • 3 초의 지연 시간 뒤에 Respawn 함수 실행
      • 플레이어는 죽은 후 3 초 뒤에 리스폰 된다.
  • 사망 했는데 남은 목숨도 없다면 게임을 종료해야 한다.
    • GameManager.Instance.EndGame();
  • 사망했다면 다시 마우스 커서가 보이도록
    • Cursor.visible = true;


public void Respawn()

플레이어가 죽었는데 아직 남은 목숨이 있다면 플레이어가 다시 리스폰 되도록 하는 처리.

    public void Respawn()
    {
        gameObject.SetActive(false);
        transform.position = Utility.GetRandomPointOnNavMesh(transform.position, 30f, NavMesh.AllAreas);

        gameObject.SetActive(true);
        playerMovement.enabled = true;
        playerShooter.enabled = true;

        playerShooter.gun.ammoRemain = 120;

        Cursor.visible = false;
    }
  • Player Character를 비활성화 해준다. SetActive(false);
    • 비활성화 하는 이유
      • 👉 📜PlayerShooter.csOnDisable() 이벤트 함수가 실행되서 Gun 총을 비활성화 하기 위하여.
    • 플레이어의 위치를 새로운 위치로 변경
      • 플레이어의 위치로부터 30 반경 내에 NavMesh의 모든 영역 중 랜덤한 위치로
  • Player Character를 활성화 해준다. SetActive(true);
    • 활성화 하는 이유
    • HandleDeath() 함수에서 비활성화 시켰던 📜PlayerMovement.cs, 📜PlayerShooter.cs 를 다시 활성화 해준다.
  • 총알을 다시 새로 채워주기
    • playerShooter.gun.ammoRemain = 120
  • 마우스 커서 다시 보이지 않게
    • Cursor.visible = false;


private void OnTriggerEnter(Collider other)

아이템과 충돌 됐을 때 실행되는 이벤트 함수.

    private void OnTriggerEnter(Collider other)
    {
        // 아이템과 충돌한 경우 해당 아이템을 사용하는 처리
        // 사망하지 않은 경우에만 아이템 사용가능
        if (!playerHealth.dead)
        {
            // 충돌한 상대방으로 부터 Item 컴포넌트를 가져오기 시도
            var item = other.GetComponent<IItem>();

            // 충돌한 상대방으로부터 Item 컴포넌트가 가져오는데 성공했다면
            if (item != null)
            {
                // Use 메서드를 실행하여 아이템 사용
                item.Use(gameObject);
                // 아이템 습득 소리 재생
                playerAudioPlayer.PlayOneShot(itemPickupClip);
            }
        }
    }
  • other
    • 충돌한 Collider가 들어 온다.
  • 플레이어가 죽은 상태면 이 이벤트 함수가 실행되지 못하도록 한다. if (!playerHealth.dead) 인 경우에만 실행하도록!
    • itetm
      • 충돌한 Collider인 other로부터 ✨IItem 컴포넌트 타입이 가져와진다면 ohter는 아이템이라는 것이다!✨ if (item != null)
        • 아이템 사용 item.Use(gameObject);
          • 다형성! 아이템 종류에 맞게 오버라이딩 된 Use 함수가 실행 된다.
        • 아이템 먹는 소리 재생


🔔 컴포넌트 설정

  • “pick up” 오디오 클립 할당
    • image
  • 게임을 실행하면 이제 아이템도 먹어지고 죽으면 리스폰 되는 것을 확인할 수 있다.


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

맨 위로 이동하기


댓글남기기