Player와 Monster를 관리할 GameManager.cs를 만들고 우선 Managers에 추가해줬다.
게임의 성격에 따라 관리하는 방식이 다르다. _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> 컬렉션!
어떤 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;
}
Camera.main.gameObject.GetOrAddComponent<CameraController>().SetPlayer(player);
ㄴ인스펙터에 드래그앤드롭으로 연결하지 않고, 코드로 _player에 UnityChan을 연결해줌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);
}
Player의 Hp가 0이되면 Destroy되도록 코드를 짰다. player가 사라진 후 ground를 클릭하면 아래와 같은 경고 메시지가 뜬다.
이는 player가 없음에도 불구하고, 마우스 클릭 시 아래와 같은 코드가 실행되고 있기 때문이다.
Monster가 Player를 감지하기 위해 그동안은 아래 코드를 사용했다.
GameObject player = GameObject.FindGameObjectWithTag("Player");
이처럼 Find코드를 사용하면 찾는데 시간이 걸린다.
❌ 기존코드
💡 수정코드
📄참고자료
[인프런] c#과 유니티로 만드는 MMORPG 게임 개발 시리즈_3. 유니티 엔진
HashSet<T
>