미니 RPG 만들기(6)_GameManager / 레벨업

개발조하·2024년 1월 7일
0

Unity

목록 보기
28/30
post-thumbnail

Player와 Monster를 관리할 GameManager.cs를 만들고 우선 Managers에 추가해줬다.

1. Player, Monster 타입별 관리

1.1 GameManager.cs

게임의 성격에 따라 관리하는 방식이 다르다. _players, _monsters, _env(퀘스트에 필요한 꽃 등) 타입별로 따로 관리할 수도 있다. 서버를 연동하면 각 player와 monster들에 식별용 고유 ID가 생기기 때문에 int형의 ID를 Key로하여 각 player와 monster GameObject를 Value로 지닌 Dictionary로 관리하는 것이 좋다.

하지만, 현재 미니 RPG에서는 player가 한명이기 때문에 아래와 같이 작성하였다. 그리고 아직 서버를 연동하기 전이라 monster도 고유 ID가 없으므로 HashSet을 사용하였다.

public class GameManager 
{
    //Dictionary<int, GameObject> _players = new Dictionary<int, GameObject>();  
    GameObject _player;
    //Dictionary<int, GameObject> _monsters = new Dictionary<int, GameObject>();  
    HashSet<GameObject> _monsters = new HashSet<GameObject>();  
}

HashSet<T>: 값이 없는 ```Dictionary<TKey, TValue> 컬렉션!

2. Spawn()

2.1 GameManager.Spawn()

어떤 GameObject를 spawn할 것인가를 구분할 enum값을 정의한다. (Define.cs)

type을 인자로 받는 Spawn(Define.WorldObject type, string path, Transform parent = null) 메서드 생성

    public GameObject Spawn(Define.WorldObject type, string path, Transform parent = null)
    {
        GameObject go = Managers.Resource.Instantiate(path, parent);

        switch (type)
        {
            case Define.WorldObject.Monster:
                _monsters.Add(go);
                break;
            case Define.WorldObject.Player:
                _player = go;
                break;
        }
        return go;
    }

2.2 Spawn() 실행하기

  • GameScene.cs
    Camera.main.gameObject.GetOrAddComponent<CameraController>().SetPlayer(player); ㄴ인스펙터에 드래그앤드롭으로 연결하지 않고, 코드로 _player에 UnityChan을 연결해줌

3. Despawn()

Despawn()는 GameObject를 매개 변수로 갖는데, 이때 이 GameObject가 어떤 type인지 알 수 있도록 GetWorldObjectType(GameObject go) 메서드가 필요하다.

BaseController.cs에 WorldObjectType 프로퍼티를 선언해주고, 각각의 MonsterController.cs와 PlayerController.cs가 Init()될 때, 각자의 type을 알려주도록 로직을 구성하자.

    public Define.WorldObject GetWorldObjectType(GameObject go)
    {
        BaseController bc = go.GetComponent<BaseController>();

        if (bc == null)
            return Define.WorldObject.Unknown;

        return bc.WorldObjectType;
    }

    public void Despawn(GameObject go)
    {
        Define.WorldObject type = GetWorldObjectType(go);

        switch (type)
        {
            case Define.WorldObject.Monster:
                {
                    if(_monsters.Contains(go))
                        _monsters.Remove(go);
                }
                break;
            case Define.WorldObject.Player:
                {
                    if (_player == go)
                        _player = null;
                }
                break;
        }
        Managers.Resource.Destroy(go);
    }

4. Destroy() 후 오류

Player의 Hp가 0이되면 Destroy되도록 코드를 짰다. player가 사라진 후 ground를 클릭하면 아래와 같은 경고 메시지가 뜬다.
이는 player가 없음에도 불구하고, 마우스 클릭 시 아래와 같은 코드가 실행되고 있기 때문이다.

5. GameManager.cs 활용하여 코드 개선

5.1 player 빨리 찾기

Monster가 Player를 감지하기 위해 그동안은 아래 코드를 사용했다.

GameObject player = GameObject.FindGameObjectWithTag("Player");

이처럼 Find코드를 사용하면 찾는데 시간이 걸린다.

  • GameManager.cs에서 GetPlayer() 생성 후 필요 시 호출
    이렇게 메서드를 활용하면 조금 더 빠르게 Player를 찾을 수 있다.

5.2 OnHitEvent()

❌ 기존코드

💡 수정코드

  • Stat.cs
  • PlayerStat.cs
  • PlayerController와 MonsterController의 OnHitEvent()메서드

6. 레벨업

  • statData에 totalExp 데이터 추가
  • 레벨에 따른 stat 값 변경하는 SetStat()메서드 추가 (PlayerStat.cs)
  • 몬스터 kill 시, 경험치 획득 (stat.cs)
  • 현재 경험치가 다음 레벨로 넘어갈 수 있는 경험치인지 비교 확인

    -> 몬스터 죽이면 exp 증가하면서 자동으로 level 상승 및 stat 재설정됨

📄참고자료
[인프런] c#과 유니티로 만드는 MMORPG 게임 개발 시리즈_3. 유니티 엔진
HashSet<T>

profile
Unity 개발자 취준생의 개발로그, Slow and steady wins the race !

0개의 댓글