public class MonsterController : CreatureController
{
Coroutine _coPatrol;
Vector3Int _destCellPos;
public override CreatureState State
{
get { return _state; }
set
{
if (_state == value)
return;
base.State = value;
if (_coPatrol != null)
{
StopCoroutine(_coPatrol);
_coPatrol = null;
}
}
}
protected override void Init()
{
base.Init();
State = CreatureState.Idle;
Dir = MoveDir.None;
}
protected override void UpdateIdle()
{
base.UpdateIdle();
if(_coPatrol == null)
{
_coPatrol = StartCoroutine("CoPatrol");
}
}
protected override void MoveToNextPos()
{
Vector3Int moveCellDir = _destCellPos - CellPos;
if (moveCellDir.x > 0)
Dir = MoveDir.Right;
else if (moveCellDir.x < 0)
Dir = MoveDir.Left;
else if (moveCellDir.y > 0)
Dir = MoveDir.Up;
else if (moveCellDir.y < 0)
Dir = MoveDir.Down;
else
Dir = MoveDir.None;
Vector3Int destPos = CellPos;
switch (Dir)
{
case MoveDir.Up:
destPos += Vector3Int.up;
break;
case MoveDir.Down:
destPos += Vector3Int.down;
break;
case MoveDir.Left:
destPos += Vector3Int.left;
break;
case MoveDir.Right:
destPos += Vector3Int.right;
break;
}
if (Managers.Map.CanGo(destPos) && Managers.Obj.Find(destPos) == null)
{
CellPos = destPos;
}
else
{
State = CreatureState.Idle;
}
}
public override void OnDamanged()
{
GameObject effect = Managers.Resource.Instantiate("Effect/DieEffect");
effect.transform.position = transform.position;
effect.GetComponent<Animator>().Play("DieStart");
GameObject.Destroy(effect, 0.5f);
Managers.Obj.Remove(gameObject);
Managers.Resource.Destroy(gameObject);
}
IEnumerator CoPatrol()
{
int waitSeconds = Random.Range(1, 4);
yield return new WaitForSeconds(waitSeconds);
for (int i = 0; i < 10; i++)
{
int xRange = Random.Range(-5, 6);
int yRange = Random.Range(-5, 6);
Vector3Int randPos = CellPos + new Vector3Int(xRange, yRange, 0);
if (Managers.Map.CanGo(randPos) && Managers.Obj.Find(randPos) == null)
{
_destCellPos = randPos;
State = CreatureState.Moving;
yield break;
}
}
State = CreatureState.Idle;
}
}
몬스터가 생성되고 CreatureState가 Idle일 때 코루틴 함수 CoPatrol이 실행되고 _coPatrol에 코루틴이 반환된다. 그러면 1~4초 마다 for문의 로직이 실행되는데 현재 위치에서 x,y 각각 -5~6이 더해진 위치가 갈 수 있는지 여부를 체크하고 만약 갈 수 있으면 도착 위치를 갱신하고 yield break 명령어를 통해 코루틴 함수를 그 시점에서 중단시킨다.
만약 for문을 10번 반복할 동안 갈 수 있는 위치를 찾지 못했으면 그대로 for문을 빠져나와 State를 Idle로 바꿔버린다.
이때 State는 CreatureController에서 virtual로 선언한 것을 override한 것인데 _coPatrol이 null이 아니라면 코루틴을 중지시키고 null로 갱신시켜 다시 CreatureController에서 UpdateController()가 호출될 때 UpdateIdle을 실행시키도록 하였다.