Hyun's Wonderwall

[유니티 공부] 랜덤 확률 버튼 미니게임 본문

Study/Unity, C#

[유니티 공부] 랜덤 확률 버튼 미니게임

Hyun_! 2024. 1. 1. 19:02

게임 프로젝트 개발 중. 각자 맡은 미니게임 구분을 공부 및 구현해오기로 했다.
내가 맡은 미니게임 2가지는 둘 다 확률에 의해 결과가 좌우된다. (순전히 운)
 
플레이어는 "fame", "money" 변수를 가지고 있다.

  • 1번째 게임 : 버튼을 누르면 특정 시간(3초)가 지난 후 확률에 따라 500~5000 사이(500 단위)로 랜덤한 값을 획득하고 그만큼 스크립트의 필드인 subs 변수의 값이 증가한다.
  • - subs는 5000으로 나눌 시의 몫이 증가할 때마다 fame이 1씩 증가한다.
  • 2번째 게임 : 버튼을 누르면 특정 시간(3초)가 지난 후 95%확률로 10000~50000 사이(5000 단위)의 돈을 얻거나 5% 확률로 2억을 얻게 된다. 얻은 만큼 money 변수의 값이 업데이트된다.

0. 카메라 및 캔버스 모바일 맞게 세팅

이렇게 맞추어준다.

 

1. C#으로 확률 구현 ("5%의 확률로~")

- Random 클래스
난수를 얻는 두 가지 방법이 있는데 첫번째 방법은 '확률' 계산, 두번째 방법은 '정수형 난수'를 얻기 위해 사용했다.

using UnityEngine; // 임포트

// 첫번째 방법
float p = Random.value; // 0~1 사이의 실수 랜덤 값을 얻고 p < 0.05f로 대소비교
// 두번째 방법
int randomNumber = Random.Range(0, 100); // 0~99 사이의 정수 랜덤 값을 얻고 randomNumber < 5로 대소비교

 

2. 유저 데이터 저장 (간단히)

- PlayerPrefs 클래스를 사용.
PlayerPrefs는 <Key, Value>로 데이터를 저장하는 클래스이다.(<식별자, 값>) int, float, string 타입의 데이터를 저장한다. 메소드 이름은 SetInt(string Key, int value), GetInt(string Key) 이런 식. // 참고: https://notyu.tistory.com/61
(C#은 메소드 이름도 대문자로 시작하는 게 원칙인 것 같다.)
GameManager.cs에 StatusText()메소드를 만들어 Start()에서 한번 호출했다. status 변수엔 씬에 있는 text mesh pro 오브젝트를 넣어주었다.
+) 뭔가... 계속 repaint해줘야 할 줄 알았는데 계속 업데이트가 정상적으로 되어서 놀랐다 (공부해봐야 할 것 같다...)

using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    public TMP_Text status;

    void Start()
    {
        StatusText();
    }
    
    public void StatusText()
    {
        status.text = "명성: " + PlayerPrefs.GetInt("Fame")
                    + "\n돈: " + PlayerPrefs.GetInt("Money") + "원";
    }
}

추후 읽어볼 자료들 https://art-life.tistory.com/131
https://you-rang.tistory.com/139
 

3. 초기화

음... 개발 중 초기화 스크립트의 필요성을 느껴서 만든 것인데 다시 보니 구조화적이지 못한 것 같다. GameManager안으로 합치는 방법이나 초기화 스크립트를 잘 만드는 법을 찾아봐야겠다.

using UnityEngine;

public class InitializeStatus : MonoBehaviour
{
    void Start()
    {
        PlayerPrefs.SetInt("Fame", 0);
        PlayerPrefs.SetInt("Money", 0);
    }
}

 

4. 씬 전환

아직 가장 좋은 방법을 모르겠어서 일단 내 마음대로 해보았다.
캔버스의 EventSystem에 SceneController.cs를 달아준 후 targetScene 필드를 통해 ChangeScene()이 호출되었을 때 이동할 씬을 입력했다. Button의 On Click에서 (EventSystem의 해당 스크립트의)  ChangeScene()을 호출했다.

using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneController : MonoBehaviour
{
    public string targetScene;
    public void ChangeScene()
    {
        SceneManager.LoadScene(targetScene); //해당 씬으로 이동
    }
}

 

5. 게임 스크립트

유튜브 게임

using UnityEngine;
using TMPro;

public class YoutubeGame : MonoBehaviour
{
    int subs; //구독자수
    public TMP_Text msg;

    public void AddSubcribers()
    {
        //subs = PlayerPrefs.GetInt("Subscribers", 0); //구독자수
        int newSubs = Random.Range(1, 11) * 500;
        int totalSubs = subs + newSubs;
        //PlayerPrefs.SetInt("Subscribers", subs);
        msg.text = "구독자 수가 " + newSubs + "명 증가하여\n" + totalSubs + "명이 되었습니다.\n";
        if (totalSubs / 5000 > subs / 5000)
        {
            PlayerPrefs.SetInt("Fame", PlayerPrefs.GetInt("Fame") + 1);
            msg.text += "명성이 1 증가했습니다.\n";
        }
        subs += newSubs;
    }
    void Start()
    {
        subs = 0;
        //PlayerPrefs.SetInt("Subscribers", subs);
        msg.text = "";
    }
}

구걸 게임 (Debug.Log()를 한번 찍어봤다)

using UnityEngine;
using TMPro;

public class BeggingGame : MonoBehaviour
{
    public TMP_Text msg;

    public void BegForMoney()
    {
        int newMoney;
        float p = Random.value;
        if (p < 0.05f)
        {
            newMoney = 200000000;
            msg.text = "2억을 얻었습니다. 해피엔딩!";
            Debug.Log("5%의 확률 성공!");
        }
        else
        {
            newMoney = Random.Range(2, 11) * 5000;
            msg.text = newMoney+"원을 얻었습니다.\n";
        }
        PlayerPrefs.SetInt("Money", PlayerPrefs.GetInt("Money") + newMoney);
    }
    void Start()
    {
        msg.text = "";
    }
}

 

6. 한글 폰트 적용

KoPub 돋움체 Medium 을 사용했다.
구글링 한 대로 따라했는데도 잘 안 돼서 무엇이 문제지 했는데, TMP 폰트를 생성해야 하는데 Text 폰트를 생성해서 그런거였다... TMP 폰트를 만들고 Dynamic 설정도 해주니 잘 적용되었다.

결과물

넣은 이미지는 밴드 실리카겔의 APEX 뮤직비디오 캡쳐이다. (이미지가 없으니 심심해서 사심을 담았다)

6. 특정 시간동안 기다리기 - 코루틴 Coroutine

아직 이 부분은 프로그래밍하지 않았다.
읽어볼 자료들: https://yeobi27.tistory.com/entry/Unity-C-Coroutine-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

[Unity] C# Coroutine 알아보기

http://theeye.pe.kr/archives/2725 Unity C# – Coroutine 알아보기 유니티에서 사용되는 코루틴(Coroutine)은 왜 필요한가? 유니티에서 화면의 변화를 일으키기 위해서는 Update() 함수 내에서 작업을 하게 됩니다.

yeobi27.tistory.com

https://kakaroo.tistory.com/92

유니티 #8 - delay (코루틴, invoke)

씬 전환시 버튼음이 플레이 되자마자 완료되지 않은 상태로 씬 전환이 되어 어색할 때가 있다. 이 때 버튼음의 시간동안 딜레이를 준 다음에 다음 씬으로 넘어가게 한다. 유니티에서 딜레이를

kakaroo.tistory.com

 
https://clack.tistory.com/50