📖 플레이어 소환에 이은 몬스터 소환을 구현할 차례인데 우선 몬스터를 구현하기 위한 에셋은 기존에 사용하던 SPUM의 확장팩을 새로 구매했다.

가격은 10달러지만, 기존에 있던 SPUM의 애니메이터를 활용할 수 있고 한번 사두면 이후에 요긴하게 사용할 수 있을 것 같다고 생각했기 때문에 바로 구매했다.
구매한 언데드 몬스터 팩을 이용해 만든 Monster Prefab은 아래 사진과 같고 간단한 오크가 칼을 쥐고 있는 몬스터로 만들었다.

[캐릭터 소환]에서 만든 Object Manager의 기본 뼈대는 아래 코드와 같다.
public class ObjectManager
{
public MyPlayerController MyPlayer { get; set; }
Dictionary<int, GameObject> _objects = new Dictionary<int, GameObject>();
public void Add(bool isPlayer = true)
{
if (MyPlayer != null)
return;
if (isPlayer)
{
// 플레이어
}
else
{
// 몬스터
}
}
}
플레이어를 소환하는 부분과 몬스터를 소환하는 부분을 분리하였는데 이번 '몬스터 소환'부분은 '플레이어 소환'부분과 매우 유사하다. 생성할 Prefab을 지정하고 플레이어와 마찬가지로 고정ID와 위치에 소환을 지정해준다.
public void Add(bool isPlayer = true)
{
if (isPlayer)
{
if (MyPlayer != null)
return;
// 플레이어
GameObject go = Managers.Resource.Instantiate("Creature/Player");
go.name = "Player";
_objects.Add(1, go);
// TODO: ID 고정값 변경
MyPlayer = go.GetComponent<MyPlayerController>();
MyPlayer.ID = 1;
// 캐릭터 정보 설정
// TODO?: 플레이어 위치를 Manager에서 직접 설정?
MyPlayer.transform.position = Vector3.up * 2.5f;
}
else
{
// 몬스터
GameObject go = Managers.Resource.Instantiate("Creature/Monster");
go.name = "Monster";
_objects.Add(2, go);
MonsterController mc = go.GetComponent<MonsterController>();
mc.ID = 2;
mc.transform.position = (Vector3.up + Vector3.right) * 2.5f;
}
}
몬스터의 움직임과 상태를 처리하는 Monster Controller는 플레이어를 담당하는 MyPlayerController와 매우 많은 부분이 겹친다. 이동속도나 중력가속도를 비롯해 애니메이터와 이동방식, Update구조 등 동작방식에서 공통된 여러 부분이 존재한다.
이를 위해 공통된 부분은 CreatureController라는 상위 Controller로 묶어 이를 상속하는 구조로 변경하였다.

CreatureController를 상속받은 'MonsterController'와 'MyPlayerController'는 각 상태에 따른 로직만 서로 다르고 재생할 애니메이션, 이동 방향과 같은 처리는 할 필요가 없다.
MyPlayerController에는 사용자의 키입력을 받는 부분은 그대로 유지하고 나머지 부분을 상위 Controller로 옮겨주었고, MonsterController에는 각 상태의 Update 함수들을 만들어 두었다.
이전까지 만들어둔 플레이어의 이동, 점프, 공격은 잘 작동하는 것을 확인하였고 아직 몬스터는 무한 대기중으로 땅위에 잘 서있는 것 까지 확인하였다.
이후에는 MonsterController의 상태 Update들을 수정해 간단한 몬스터AI를 만들고 서버작업에 들어갈 예정이다.
