0. 들어가기 전에
재화, 점토 판매 UI 를 추가했다. 점토 판매 기능은 아직 UI 만 만들고 기능은 추가하지 않았다.
재화 UI 는 돈이나 애정을 얻었을 때, 그냥 text 로 바로 반영되는 것이 아니라 숫자가 서서히 올라가는 것처럼 보이도록 하는 효과를 주었다.
1. UI 제작
일단 재화와 점토 판매 UI 를 제작했다.
1.1 점토 판매 UI
다 자란 점토를 점토 판매 UI 로 드래그 한 후 내려 놓으면 팔리도록 하는 기능을 만들려고 한다.
이를 위해서 점토 판매 UI 를 만들어주었다. 주머니가 버튼으로 되어있는데, 나중에 Event Trigger 를 이용해서 마우스가 진입했는지 아닌지의 여부로 판매 여부를 판단할 것이다.
1.2 재화 UI
수치를 확인할 수 있도록 하는 UI 를 제작했다.
수치에 변동 사항이 생길 때마다 text UI 에 반영되도록 했다.
변동 사항이 생겼을 때, 그 값을 바로 text 에 집어 넣으면 생동감이 없기에 숫자가 서서히 오르도록 했다. 이를 위해서 스크립트로 구현해야 했다.
2. 스크립트
이번에 만든 스크립트는 GameManager 와 GameDataUIController 이다.
2.1 GameManager 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
[Header("Game Data")]
public float love; // 애정
public float gold; // 골드
[Header("Game Manager")]
public static GameManager instance; // 싱글톤 이용하기 위함
[Header("GameDataUI")]
public GameDataUIController gameDataUI;
[Header("Coroutine")]
public Coroutine updateTextUICoroutine;
private void Awake()
{
// 싱글톤 패턴
if (instance != null && instance != this)
{
// 이미 존재하면 새로 만든거 없애
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(gameObject); // 얘는 다른 씬으로 전환되어도 안 없앨 거임
}
void Start()
{
GetGold(0);
GetLove(0);
GetLove(10000);
}
// 재화 얻는 함수
public void GetGold(float capacity)
{
// 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함.
if (updateTextUICoroutine != null)
{
StopCoroutine(updateTextUICoroutine);
}
updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("gold", gold + capacity, gold));
gold += capacity;
//PlayerPrefs.SetFloat("Gold", gold); // 데이터 저장
}
public void GetLove(float capacity)
{
// 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함.
if (updateTextUICoroutine != null)
{
StopCoroutine(updateTextUICoroutine);
}
updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("love", love + capacity, love));
love += capacity;
//PlayerPrefs.SetFloat("Love", love); // 데이터 저장
}
}
2.2 GameManager 스크립트 설명
GameManager 스크립트에 대한 설명은 다음과 같다.
1. 변수
Game Data 를 관리하기 위한 변수인 love 와 gold 를 선언했다.
GameManager 는 싱글톤 패턴을 이용할 것이기 때문에 GameManger 타입의 instance 변수도 선언했다.
GameManager 는 GameDataUIContoller 타입의 gameDataUI 변수를 가지는데 이는 gameDataUI 의 UpdateTextUI 코루틴을 이용하기 위함이다.
현재 시작한 코루틴을 지정하기 위해 Coroutine 타입의 updateTextUICoroutine 변수를 선언했다. 이는 코루틴을 중지시킬 때 중지시킬 특정 코루틴을 명확히 지정하기 위함이다.
[Header("Game Data")]
public float love; // 애정
public float gold; // 골드
[Header("Game Manager")]
public static GameManager instance; // 싱글톤 이용하기 위함
[Header("GameDataUI")]
public GameDataUIController gameDataUI;
[Header("Coroutine")]
public Coroutine updateTextUICoroutine;
2. Awake()
싱글톤 패턴을 이용하기 위해 선언했던 instance 변수에 GameManager 게임 오브젝트를 할당한다. 자기 자신을 할당해야 하기 때문에 this 를 이용한다.
근데 만약 이미 존재한다면 새로 생성된 게임 오브젝트를 삭제하도록 했다.
private void Awake()
{
// 싱글톤 패턴
if (instance != null && instance != this)
{
// 이미 존재하면 새로 만든거 없애
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(gameObject); // 얘는 다른 씬으로 전환되어도 안 없앨 거임
}
3. Start()
재화가 서서히 증가하는 모습이 text 에 반영되는지 확인하기 위함이다. 나중엔 없앨 것.
void Start()
{
GetGold(0);
GetLove(0);
GetLove(10000);
}
4. GetGold(float capacity), GetLove(float capacity)
사실 두 함수는 대상만 다르지 로직은 동일하다.
이 함수에서는 gameDataUI 타입의 게임 오브젝트의 UpdateTextUI 코루틴을 호출하는 일을 한다. 코루틴을 호출할 때 매개변수를 넘겨주어야 하는데 차례로 의미하는 것은 다음과 같다.
어떤 텍스트를 업데이트 할 것인가, 목표치, 현재 재화
updataTextUICoroutine 에 코루틴을 시작하면 반환되는 값을 할당해놓고, 다음에 해당 코루틴을 중지시킬 때 사용한다.
게임 데이터를 저장하기 위해 PlayerPrefs 를 적어놨지만 지금은 주석처리 해놨다. 다음에 이용할 것이다.
// 재화 얻는 함수
public void GetGold(float capacity)
{
// 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함.
if (updateTextUICoroutine != null)
{
StopCoroutine(updateTextUICoroutine);
}
updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("gold", gold + capacity, gold));
gold += capacity;
//PlayerPrefs.SetFloat("Gold", gold); // 데이터 저장
}
public void GetLove(float capacity)
{
// 이미 코루틴이 종료되지 않은 중에 동일한게 또 들어오면 겹쳐서 반영이 돼서 이상하게 될 수 있으므로 null 인지 판단해야함.
if (updateTextUICoroutine != null)
{
StopCoroutine(updateTextUICoroutine);
}
updateTextUICoroutine = StartCoroutine(gameDataUI.UpdateTextUI("love", love + capacity, love));
love += capacity;
//PlayerPrefs.SetFloat("Love", love); // 데이터 저장
}
2.3 GameDataUIContoller 스크립트
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.WSA;
public class GameDataUIController : MonoBehaviour
{
[Header("Game Data UI")]
public Text loveText;
public Text goldText;
public IEnumerator UpdateTextUI(string name, float target, float current)
{
// Text 가 참조 타입이라 가능한것..
Text targetText = null; // 변경할 대상 text 할당용 변수
if (name == "gold")
{
targetText = goldText; // goldText 게임 오브젝트 할당
}
else if (name == "love")
{
targetText = loveText; // loveText 게임 오브젝트 할당
}
float duration = 0.5f; // 카운팅에 걸리는 시간 설정
float offset = (target - current) / duration;
while (current < target)
{
current += offset * Time.deltaTime;
targetText.text = (current).ToString("N0");
yield return null; // 다음 프레임까지 기다림
}
current = target;
targetText.text = (current).ToString("N0");
}
}
2.4 GameDataUIContoller 스크립트 설명
GameDataUIController 스크립트에 대한 설명은 다음과 같다.
1. 변수
text UI 의 text 를 업데이트 하기 위해 선언한 변수이다.
[Header("Game Data UI")]
public Text loveText;
public Text goldText;
2. UpdateTextUI(string name, float target, float current)
UpdateTextUI 코루틴을 만들었다.
재화가 서서히 증가하는 것처럼 보이도록 만들기 위해서 구현한 코루틴이다.
name 의 값으로 gold 와 love 중 어떤 텍스트를 업데이트 할 것인지 여부를 결정했다.
그리고 수치가 업데이트 되는 시간을 duration 으로 지정해서 그 시간동안 재화가 업데이트 되도록 했다.
text 에는 string 타입의 값을 넣어야 하기 때문에 그냥 current 값을 넣을 수가 없어서 string 으로 변환해주었다. 변환할 때 "N0" 을 이용하면 세자리마다 알아서 ',' 를 붙여준다. 찾아보니 이거를 서식 문자열이라고 부른다고 하더라.
public IEnumerator UpdateTextUI(string name, float target, float current)
{
// Text 가 참조 타입이라 가능한것..
Text targetText = null; // 변경할 대상 text 할당용 변수
if (name == "gold")
{
targetText = goldText; // goldText 게임 오브젝트 할당
}
else if (name == "love")
{
targetText = loveText; // loveText 게임 오브젝트 할당
}
float duration = 0.5f; // 카운팅에 걸리는 시간 설정
float offset = (target - current) / duration;
while (current < target)
{
current += offset * Time.deltaTime;
targetText.text = (current).ToString("N0");
yield return null; // 다음 프레임까지 기다림
}
current = target;
targetText.text = (current).ToString("N0");
}
3. 결과물
정삭적으로 작동하는 모습을 확인할 수 있다.
4. 참고자료
오늘 이용한 개념들에 대해 잘 정리해놓은 글이 있어서 가져왔다.
4.1 서식 문자열
[18일차] 유니티 (카운트 업, 소수점 표시.. : 네이버블로그
4.2 PlayerPrefs
유니티에서 데이터 저장하기: PlayerPrefs를 활용한 간단한 저장 시스템