
금일 배운 것을 TIL 로 올리려 했으나, 노트용 자료가 덜 올라와 자료 정리가 좀 애매해서,
실습시간에 진행한 간단한 2D 게임에 대해 소개 한다.
GamePlayerController.cs; 플레이어 제어 스크립트GamePlayerAnimation.cs; 플레이어 Animation 스크립트GameManager.cs; Game Score 저장을 위한 싱글톤 오브젝트CoinSpawner.cs; Coin object 관리를 위한 싱글톤 오브젝트UIControl.cs; 화면에 보여줄 UI 에 대한 스크립트Coin.cs; Coin 이 가져야할 행동에 대한 스크립트Send Message vs Invoke Unity EventsSend Message.InputValueInpuAction.CallbackContext로 사용할 수 없음.InputAction.CallbackContext는 Invoke Unity Events로만 사용 가능.Invoke Unity Events 사용시 추가 주의 사항Inspector 내 Events 에 관련 함수를 수동으로 Bind 해주어야함.Collision으로 받음. -> 동작 안함.Collision2D가 별도로 존재.Object Pool Pattern을 활용함.개인적인 Backup 느낌으로 적는 것 입니다.
using System;
using System.Collections;
using UnityEngine;
public class Coin : MonoBehaviour
{
public int cost = 100;
public void OnEnable()
{
StartCoroutine(Discard());
}
public void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag("Ground"))
{
DownCost();
}
else if (other.gameObject.CompareTag("Player"))
{
TagPlayer();
}
}
private void DownCost()
{
cost -= 10;
}
private void TagPlayer()
{
GameManager.Instance.Score += cost;
ReturnCoin();
}
private IEnumerator Discard()
{
yield return new WaitForSeconds(10f);
ReturnCoin();
}
private void ReturnCoin()
{
gameObject.SetActive(false);
CoinSpwaner.Instance.PushCoin(gameObject);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CoinSpwaner : MonoBehaviour
{
private static CoinSpwaner _instance;
public static CoinSpwaner Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<CoinSpwaner>();
}
return _instance;
}
}
[SerializeField] private GameObject coinPrefab;
Stack<GameObject> coinStack = new();
private void Awake()
{
Init();
}
private void Init()
{
for (int i = 0; i < 5; i++)
PushCoin();
StartCoroutine(SpawnCoin());
}
private IEnumerator SpawnCoin()
{
while (!GameManager.Instance.IsGameOver)
{
yield return new WaitForSeconds(Random.Range(1f, 2.5f));
if (coinStack.Count =< 0)
PushCoin();
GameObject coin = coinStack.Pop();
coin.transform.position = new Vector2(Random.Range(-12, 12), 9);
coin.SetActive(true);
}
}
private void PushCoin()
{
GameObject coin = Instantiate(coinPrefab);
coin.SetActive(false);
coinStack.Push(coin);
}
public void PushCoin(GameObject coin)
{
coinStack.Push(coin);
}
}
using UnityEngine;
using UnityEngine.Events;
public class GameManager : MonoBehaviour
{
private static GameManager _instance;
public static GameManager Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<GameManager>();
}
return _instance;
}
}
public UnityEvent<int> OnScoreChanged;
private int _score = 0;
public int Score
{
get
{
return _score;
}
set
{
_score = value;
OnScoreChanged?.Invoke(value);
}
}
public bool IsGameOver = false;
}
using UnityEngine;
using UnityEngine.InputSystem;
public class GamePlayerAnimation : MonoBehaviour
{
private float _direction;
private Animator _animator;
private SpriteRenderer _spriteRenderer;
private void Awake()
{
_animator = GetComponent<Animator>();
_spriteRenderer = GetComponent<SpriteRenderer>();
}
public void OnMove(InputAction.CallbackContext context)
{
if (context.performed)
{
_direction = context.ReadValue<Vector2>().x;
if (_direction < 0) _spriteRenderer.flipX = true;
else if (_direction > 0) _spriteRenderer.flipX = false;
_animator.SetBool("IsRun", true);
}
else if (context.canceled)
{
_animator.SetBool("IsRun", false);
}
}
}
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
public class GamePlayerController : MonoBehaviour
{
private Vector2 _moveInput;
[SerializeField][Range(0.5f, 10f)] private float _moveSpeed;
private void Update()
{
transform.Translate(_moveInput * (_moveSpeed * Time.deltaTime));
}
public void OnMove(InputAction.CallbackContext context)
{
Vector2 direction = context.ReadValue<Vector2>();
_moveInput = new Vector2(direction.x, 0);
}
}
using TMPro;
using UnityEngine;
public class UIControl : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _ScoreText;
private void Start()
{
OnChangeScore(0);
}
private void OnEnable()
{
GameManager.Instance.OnScoreChanged.AddListener(OnChangeScore);
}
private void OnDisable()
{
GameManager.Instance.OnScoreChanged.RemoveListener(OnChangeScore);
}
private void OnChangeScore(int score)
{
_ScoreText.text = score.ToString();
}
}