Unity - Dodge

땡구의 개발일지·2025년 4월 23일

Unity마스터

목록 보기
16/78
post-thumbnail

수업 중 진행된 내용은 생략한다. 추가적으로 구현한 기능만 기술함

스코어

  • 게임이 진행 중일때 1초마다 점수가 오름과 동시에 점수를 출력한다
  • 최대 스코어는 따로 표기하기

문제 1

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

public class ScoreUI : MonoBehaviour
{
    [SerializeField] TMP_Text scoreOutput;

    private void OnEnable()
    {
        SetScore();

    }
    private void Update()
    {
        
    }
    void SetScore()
    {
        scoreOutput.text = $"SCORE: {GameManager.instance.score}";
    }
}
  • 이렇게 하니까 UIOnEnabled()GameManagerAwake()보다 더 빨라서 instance가 존재하지 않는다

해결

  • 스코어UI를 비활성화로 세팅하고, 게임 시작에 맞춰서 활성화 해서 표시하도록 한다
public class ScoreUI : MonoBehaviour
{
    [SerializeField] TMP_Text scoreOutput;

    // 1초마다 점수 늘리기
    YieldInstruction oneSecond;
    Coroutine ScoreUpRoutine;
    private void Awake()
    {
        oneSecond = new WaitForSeconds(1f);
    }

    private void OnEnable()
    {
        SetScore();
        if (ScoreUpRoutine == null)
        {
            ScoreUpRoutine = StartCoroutine(ScoreUp());
        }
    }
    private void OnDisable()
    {
        if (ScoreUpRoutine != null)
        {
            StopCoroutine(ScoreUpRoutine);
            ScoreUpRoutine = null;
        }
    }

    void SetScore()
    {
        if(GameManager.instance.maxScore!= 0)
        {
            scoreOutput.text = $"TOP SCORE: {GameManager.instance.maxScore}\nSCORE: {GameManager.instance.score}";
        }
        else
        {
            scoreOutput.text = $"SCORE: {GameManager.instance.score}";
        }
    }

    IEnumerator ScoreUp()
    {
        // 게임 오버이면 점수가 오르지 않는다
        while(!GameManager.instance.IsGameOver)
        {
            SetScore();
            yield return oneSecond;
            // 1초마다 점수 증가
            GameManager.instance.score += 10;

        }
    }
}

최대스코어

  • 게임이 끝났을 때, 최고 기록이면 New Record로 표현
  • 최고기록은 0 점이 아닌 경우(한 번 이상 기록을 세운경우)에 스코어 위에 표현한다
public class RecordUI : MonoBehaviour
{
    [SerializeField] TMP_Text recordOutput;
    private void OnEnable()
    {
        PrintRecord();
    }
    void PrintRecord()
    {
        if(GameManager.instance.score == GameManager.instance.maxScore)
        {
            recordOutput.text = $"NEW RECORD!!!\n{GameManager.instance.score}";
        }
        else
        {
            recordOutput.text = $"SCORE: {GameManager.instance.score}";
        }
    }
}
  • 기존의 최고기록과 같은 점수여도 New Record가 뜬다. 점수 스크립트를 조금 수정한다
  • GameManager 스크립트 수정
// 게임 끝낫을 때 작업 = 게임오버
public void GameOver()
{
    // 게임오버 로직
    IsGameOver = true;
    // 플레이어 비활성화
    playerObject.SetActive(false);
    // 게임 오버 화면 띄우기
    gameOverPanel.SetActive(true);
    // 스코어 화면 비활성화
    scoreText.SetActive(false);
    // 최고 점수 갱신시 최신화
    if (score > maxScore)
    {
        maxScore = score;
    }
    // 스코어 초기화
    score = 0;
    // hp 상태 비활성화
    hpText.SetActive(false);
}
  • 스코어 화면 비활성화 당시에 스코어가 최고 스코어보다 높으면 New Record가 된다
  • 이후 최고 점수를 현재의 스코어로 등록, 스코어는 초기화 한다

플레이어의 남은 체력 표기

  • 화면 좌측에 남은 체력을 표기한다

문제 2

  • 플레이어의 체력을 UI 로 업데이트 하려고 한다. 이벤트로 체력이 감소하거나, 게임이 시작할 때만 업데이트 하려고 하는데, 플레이어의 체력의 변화를 어떻게 감지해서 프린트 할까
  • 플레이어컨트롤러 컴포넌트에 유니티이벤트를 추가한다. 그리고 플레이어 체력이 감소할 때 이벤트에 HPUI 컴포넌트의 함수를 추가하려고 하면 개체참조가 필요해서 불가능
OnHPChanged.AddListener(HPUI.PrintHP(playerHP));
  • HPUI쪽에서는 언제 체력이 감소하는지 알 수 없으니 마찬가지로 이벤트 추가 불가능

해결

  • 이벤트로 하는 방법은 아무래도 GameManager에 HPUI의 프린트 기능을 넣는 수밖에 없다. 이번에는 그냥 업데이트에서 체력이 변화 할 때만 바꾸기로 했다
public class HPUI : MonoBehaviour
{
    [SerializeField] TMP_Text HPText;
    // 체력을 받기 위한 필드
    [SerializeField] GameObject playerObject;
    private PlayerController player;
    private int hPCount;
    private void OnEnable()
    {
        player = playerObject.GetComponent<PlayerController>();
        hPCount = player.PlayerHP;
        PrintHP(hPCount);
    }
    private void Update()
    {
        if(hPCount != player.PlayerHP)
        {
            PrintHP(player.PlayerHP);
            hPCount = player.PlayerHP;
        }
    }
    public void PrintHP(int hp)
    {
        HPText.text = $"HP: {hp}";
    }
}

무적 타임 넣기

  • 생각보다 체력이 너무 훅훅 깎인다. 1초정도는 무적타임을 줄 수 있게 코루틴으로 구현해본다
private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("Bullet") && playerHP > 0)
    {
        if (invincibleRoutine == null)
        {
            invincibleRoutine = StartCoroutine(TakeHit());
        }
    }
}

IEnumerator TakeHit()
{
    playerHP--;

    if (playerHP == 0)
    {
        GameManager.instance.OnGameOver.Invoke();
    }
    yield return invincibleTime;
    invincibleRoutine = null;
}

문제

  • 문제가 아니라면 아닐 수 있는데, 무적 시간동안 깜빡거림 또는 캐릭터 색깔을 다르게 표현해서 무적 시간이라는 것을 표현하고 싶다

게임 화면





추가로 구현할 만한 요소

시간이 지날수록 적의 범위, 총알 속도 증가

시간에 따른 적 추가

profile
개발 박살내자

0개의 댓글