내일배움캠프 Unity 24일차 TIL - 팀 십장생 - 팀 프로젝트 시작

Wooooo·2023년 11월 30일
0

내일배움캠프Unity

목록 보기
26/94

오늘의 키워드

오늘 두 번째 팀 프로젝트가 시작됐다. 유니티를 이용해서 협업이다.


팀 회의

구현할 게임의 장르를 정하고, 대략적인 스토리 컨셉과 와이어 프레임을 구상했다.


GameManager.cs

나는 게임 매니저를 구현하기로 했다.
그런데 아직 게임을 굴리기에는 프로젝트에 아무것도 없기 때문에 대략적인 틀만 잡아줬다.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class GameManager : MonoBehaviour
{
    protected static GameManager instance;

    public float stageLapseTime;

    /// <summary>
    /// player 객체 참조 <br/>
    /// 추후에 자료형을 플레이어 클래스로 바꿔야함.
    /// </summary>
    public Player player;

    /// <summary>
    /// stage에 생성된 monster들을 담을 리스트 <br/>
    /// 추후에 자료형을 몬스터들의 최상위 클래스로 바꿔야함.
    /// </summary>
    public List<GameObject> monsters;

    /// <summary>
    /// stage에 생성된 item들을 담을 리스트 <br/>
    /// 추후에 자료형을 dropable item들의 상위 클래스로 바꿔야함.
    /// </summary>
    public List<GameObject> items;

    [Header("Events")]
    public UnityEvent OnGameStart;
    public UnityEvent OnGameOver;
    public UnityEvent OnStageClear;
    public UnityEvent OnStageFail;

    public static GameManager Instance
    {
        get
        {
            if (instance == null)
            {
                // Data Manager면 몰라도 얘는 생성할 필요 없을 듯?
                throw new NullReferenceException();
            }
            return instance;
        }
    }

    private GameManager() { }

    protected virtual void Awake()
    {
        if (instance == null)
            instance = this;
    }

    protected virtual void Start()
    {
        Time.timeScale = 1f;
        OnGameStart?.Invoke();
    }

    protected virtual void Update()
    {
        stageLapseTime += Time.deltaTime;
    }

    public virtual void GameOver(bool isGameClear = false)
    {
        Time.timeScale = 0f;
        OnGameOver?.Invoke();
        if (isGameClear) OnStageClear?.Invoke();
        else OnStageFail?.Invoke();
    }
}

싱글톤으로 구현했고,
현재 스테이지의 경과시간과 플레이어와 몬스터들을 참조하기위한 변수들을 만들어줬다.
스테이지의 시작, 종료, 성공, 실패 여부에 따라 호출될 이벤트들도 선언만 해줬다.

너무 금방 끝내서 게임 데이터들을 관리할 DataManager도 만들었다.

using System;
using UnityEngine;

public class DataManager : MonoBehaviour
{
    private static DataManager instance;

    public PlayerData playerData;

    public static DataManager Instance
    {
        get
        {
            if (instance == null)
            {
                var obj = new GameObject(nameof(DataManager));
                instance = obj.AddComponent<DataManager>();
                instance.Initialize();
            }
            return instance;
        }
    }

    private DataManager() { }

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            instance.Initialize();
        }
    }

    private void Start()
    {
        if (instance != this)
            Destroy(gameObject);
    }

    private void OnDestroy()
    {
        if (instance == this)
        {
            Debug.Log($"{name} call {nameof(OnDestroy)}");
            SaveData();
        }
    }

    private void Initialize()
    {
        // 각종 정보들을 초기화
        if (!LoadData())
        {
            // 불러올 수 없다면 기본값으로 세팅
            Debug.Log($"{name} call {nameof(LoadData)} is fail. redirect {nameof(CreateDefaultData)}...");
            CreateDefaultData();
        }

        DontDestroyOnLoad(gameObject);
    }

    public bool SaveData()
    {
        try
        {
            // Save data..
            var playerDataJson = JsonUtility.ToJson(playerData);
            PlayerPrefs.SetString(nameof(playerData), playerDataJson);
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            return false;
        }
        Debug.Log($"{name} call {nameof(SaveData)} is success");
        return true;
    }

    public bool LoadData()
    {
        try
        {
            // Load data..
            var playerDataJson = PlayerPrefs.GetString(nameof(playerData));
            playerData = JsonUtility.FromJson<PlayerData>(playerDataJson);
        }
        catch (Exception e)
        {
            Debug.LogError(e.Message);
            return false;
        }
        Debug.Log($"{name} call {nameof(LoadData)} is success");
        return true;
    }

    public void CreateDefaultData()
    {
        // 모든 데이터를 기본값으로 설정...
        playerData = new();
    }
}

/// <summary>
/// 플레이어 캐릭터와 관련된 정보 중에 저장이 필요할 것 같으면 여기에 추가해주시면 됩니다.
/// </summary>
[System.Serializable]
public class PlayerData
{
    public int maxHp;
    public int atk;
    public int speed;
    public int level;
    public int currentExp;
    public int money;

    public PlayerData()
    {
        maxHp = 100;
        level = 1;
        currentExp = 0;
        money = 0;
    }
}

이것도 싱글톤으로 만들었고, 씬이 전환되도 정보가 유실되지 않도록 구현해봤다.
게임이 켜지면 자동으로 데이터를 로드하고, 꺼지면 자동으로 세이브하도록 짜봤다.


Merge Conflict

첫 날부터 Git 충돌이 났다. 저번에 했던 프로젝트는 C# 콘솔 프로젝트라서 큰 충돌 없이 마무리했었는데, 유니티는 확실히 콘솔 때보다 어려운 것 같다.
meta파일, asset파일 여러 군데에서 충돌이 나서 많이 어지러웠다.
이번 프로젝트에서 보다 확실하고 체계적으로 Git 관리를 해야겠다고 느꼈다.

profile
game developer

0개의 댓글