일단 당면 과제가 에너미의 이동과 센서를 구현하는 거다. 이게 사놓은 행동 트리 에셋을 이용하면 쉽게 구현할 수 있을 듯싶은데 그게 유니티 자체 길 찾기 시스템과 실시간 RPG를 염두에 두고 만든 거라서 내가 기존에 만들어 놓은 그리드 기반 시스템과 호환이 되지 않는 문제가 있다. 따라서 그건 나중에 히트맨 같은 실시간 잠입 게임을 만들 때 써야 할 듯싶다. 그전에 저번에 턴 관련해서 마무리 짓지 못한 것부터 해결해야겠다.
턴제게임에서 에너미 인공지능이 기능하기 위해서는 자신의 턴이 왔다는 걸 먼저 감지를 해야 할 듯싶다. 물론 에너미 턴의 연산을 최적화하기 위해서는 플레이어 탄에서 틈틈이 일정 부분 생각을 하는 팁도 있겠지만... 일단은 에너미 턴으로 왔을 때부터 생각을 하도록 코딩을 할 생각이다.
우선 코드를 보면 게임메니저에서 이 두 함수가 이 턴을 넘기는 역할을 하고 있다. 이게 턴이 넘어간 걸 업데이트로 감지를 할 수도 있겠지만 일단 턴을 감지하는걸 이들이 발동되었을 때에 한해서 진행하도록 하면 될 듯싶다.
진행하다가 문득 에너미가 순차적으로 이동을 해야 하는지 동시에 이동을 해야 하는지 의문이 들었다. 일단은 안개가 있는 곳에서는 기다리는 시간이 지루하니 순간이동을 해야 한다. 안개가 없는 곳에서는 컴터가 순차적으로 이동하는 걸 보여주는 게 게임 플레이상 보다 바람직한 듯싶다. 한꺼번에 움직여 버리면 어떻게 돌아가는 건지 전황 파악이 어려우니 말이다. 죽이려고 이동했는데 다른 놈이 죽여버러서 인공지능이 꼬이는 경우도 발생할 거구 말이다.
순차적으로 진행하게 하려면 전체적으로 조율하는건 게임 매니저에서 하고 구체적인 건 각 에너미 클래스에서 조율하도록 하는 게 좋을 듯싶다. 왠지 이걸 게임 매니저랑 구별하는 게 좋을 듯해서 별도의 EnemyAI 클래스로 만들었다.
while (Vector3.Distance (destinationPos, transform.position) > 0.01f)
{
yieldreturnnull;
}
iTween.Stop (gameObject);
transform.position=destinationPos;
enemy.enemyActiveState=EnemyActiveState.Ready;
}
}
그냥 복사 붙여 넣기 수준이다. 다이어트가 필요할까 싶기도 한데 일단은 그냥 놓아두자.
// start
publicvoidIndicateUnit (List<TileNode> way)
{
way.Reverse();
StartCoroutine (Indicator (MakeTransform (way)));
}
이 부분이 일종의 스타트 함수인 듯싶다. 이제 클래스가 실제로 작동을 잘하는지 테스트를 해보면 될 듯싶다. 잘 작동하면 이 두 클래스를 무버로 통합할 수도 있긴 할 텐데. 아직 잘은 몰라서 그래도 시도는 해봐야겠지.
voidStart()
{
var testList =newList<TileNode>();
testList.Add(FindObjectOfType<TileNode>());
moving.IndicateUnit (testList);
}
간단한 테스트 코드인데 매우 잘 작동을 한다. 이제 두 클래스를 통합하는 작업을 해야겠다. 근데... 음... 먼가 복잡하다. 나중에 잘하는 사람한테 물어보도록 하고 일단 넘어가야겠다.
// void Start()
// {
// var testList = new List<TileNode>();
// testList.Add(FindObjectOfType<TileNode>());
// moving.IndicateUnit (testList);
// }
테스트 코드는 비활성화한다. 그다음으로 센서를 구현해야 할 거 같다. 전지적으로 판단을 내리는 것과 제한된 상황에서 판단을 내리는 두 가지를 좀 구분을 해서 만들어야 할 듯싶다. 머랄까 다 알고 있는데... 적절한 연기를 해야 하는 부분이 있어야 하기 때문이다. 이게 게임 인공지능과 그냥 인공지능의 큰 차이중 하나인 듯 싶다. 결국 목적은 극적으로 져주는 거니 말이다.
일단은 우선적으로 만들어야 할게 엑스컴에 보면 그냥 움직이다가 플레이어가 근처에 있을 때 장애물로 산개하는 거다. 이게 엑스컴 라이크 장르별로 다르긴 한데 우선은 엑스컴 리메이크에 충실하게 만들고 나중에 적절히 바꿔야 할 듯싶다.
반응을 하는 걸 구현하고 그걸 응용해서 장애물을 만들고 산개하는 걸 만들어야겠다. 장애물로 산개하는 건 효용 기반을 어느 정도 조합해서 만들어야 할 듯싶다. 완엄패라고 좋다고 이동했는데 아군 라인속으로 들어간다든지 해버리면 골치 아프니 말이다. 왠지 효용 기반으로 짤 때 공식을 만드는 게 쉽지는 않을듯 싶다. 꽤 많은 시행착오가 필요할듯 싶다.
일단 애드라고 하는 이걸 만드는게 급선무인 듯싶다. 보통 이건 플레이어가 맞닿게 할 수 있고 에너미가 맞닿게 할 수가 있다. 따라서 플레이어가 이동을 했을 때나. 플레이어가 에너미에게 공격을 했을때라든지. 이럴래 발동이 되게 하는거니. 게임 매니저에서 관리를 해야 할듯 싶다. 아글고 한 3명정도 에너미를 팀을 이루게 하는거가 필요하니 그룹을 짓게 하는것도 필요할듯 싶다.
그전에 플레이어가 이동을 했을때 감지하는 걸 만들어야겠다. 아 그리고 전장의 안개도 만들어야 할 듯싶다. 먼가 해야 할게 한두 개가 아닌 듯싶다. 일단 전장의 안개는 좀 후반부로 미루어야 겠다.
음... 이걸 만드는 방식을 생각해 봤는데. 플레이어와 에너미의 거리를 기록하는 방식이 하나가 있을 거다. 이렇게 하면 플레이어와 에너미의 숫자가 많아지면 좀 복잡할 수도 있을 듯싶다. 일단 플레이어는 최대 6명으로 제약이 되니 문제가 안될 수도 있지만 말이다. 아니면 에너미에게 범위를 만드는 방식이 있을수도 있다. 아니면 플레이어에게 범위를 만드는 방식도 있을수 있다. 일단은 에너미에게 범위를 만드는 방식이 합당해 보인다. 다만 나중에 은신시 장애물이 있어서 범위 내에 있지만 보이지 않는 걸로 처러할 경우에 제하는게 난관이 될수도 있겠다.
이걸 디비니티 방식으로 하면 행동 트리 에셋에 있는 센서를 활용할 수가 있어서 편할 듯싶다. 그런데 만들려고 하려고 하니까 머리가 좀 깨지는 듯싶다. 차기작은 그리드 방식이 아니라 디비니티 방식으로 해야겠다.
일단 고민되는 게 사각 범위로 해야 하는지 아니면 조금 현실적이게 원형으로 해야 하는지 다. 엑스컴 보면 사각형이 아니라 언뜻 보면 8 각형처럼 느껴지기도 한다.
이게 합리적인 이동 범위라는 게 정해진 절대 숫자가 있는 듯싶다. 이런 식으로 먼가 딱 안 맞는 게 있어서 말이다.
일단 헥사로 딱 떨어지는 경우를 정리를 하면
이동력이 3인 경우이다. 오브젝트의 크기는 12...
이동력이 4인 경우는 좀 덜 이쁘게 나온다. 오브젝트 크기는 16...
이동력이 5인 경우. 오브젝트의 크기는 20...
기본이 동력을 3 4 5중 하나로 잡아야 될 듯싶다.
기본이 동력을 5로 한다면 최대 이동 범위는 이렇게 되고 40이다. 나름 그럴듯하다.
기본 이동력을 3으로 잡으면 최대 이동 범위는 이렇게 되고 이것도 나름 그럴듯하다. 24이다.
작전 반경과 오브젝트 배치 반경 등 많은 요소가 영향을 받을 수밖에 없기 때문에 둘 중 하나를 신중하게 결정해야 할 듯싶다.
아무래도 기본 이동력이 5이고 최대 이동력이 10은 돼야 좀 움직이는 맛이 있고 그러지 않을까 싶다.
카메라 뷰나 각도는 이 정도는 돼야 답답하진 않을 듯싶다. 한 번에 10칸씩 이동하니 말이다.
최대 이동 가능 범위가 이게 딱 이동 칸이라는 맞아떨어지는 숫자가 아니다 보니 조금 계산적으로 플레이하는 사람에겐 불합리 할수도 있다. 어느정도 직관적으로 감으로 플레이 하는 사람에게는 오히려 이 시스템이 보다 합리적이지 않나 싶다.
엑스컴의 경우에는 7칸인데 한 타 일의 크기가 좀 더 작다. 내쪽이 좀 더 뛰엄뛰엄이다. 따라서 체감상 느낌은 비슷하지 않을까 싶다. 보통 엄패물이 5칸씩 떨어져 있으니. 엄패물이 3칸 내에는 있어야 안전하게 이동할 수 있을 듯싶다.
그냥 7칸 28로 하는 게 좋을 듯싶다. 5칸으로 하면 너무 엄패물들이 붙게 되니 맵이 갑갑해 보일 수도 있고 말이다. 최대 거리인 56도 꽤 합리적이다.
일단 이를 인지하는 레이어 마스크를 따로 만들어야 할 듯싶은데. 우선 이동에 관해서는 이동 범위가 7인걸 먼저 만들고. 한 번에 최대로 이동할 수 있는 시스템을 만들어야 할 듯싶다. 14 이동범 위중 7 이동범 위를 빼면 될 듯싶다.
우선 타일 노드 클래스로 가서 해당 영역을 표시하는 것부터 만들고 이동 가능 영역을 제한하는 것을 만들어야 할 듯싶다. 노드가 일정한 에어리어에서만 클릭을 동작하게 말이다.
일단 노멀 한 타일, 1 행동력을 소모해서 이동할 수 있는 타일, 2 행동력을 소모해서 이동할수 있는 타일, 그리고 이동할수 없는 타일 이런 게 나누어야 하니 enum을 사용하는 게 합당할 듯싶다. 나중에는 불이 붇은 타일과 독 타일도 추가해야 할듯 싶다.
일단 맥스 에어리어도 타일을 만들때 껐다가 키도록 만들어준다. 그 다음에 해야 할께 타일을 만들때 맥스에어리어 해당하는 걸 만들어야 할 듯싶다. 단 맥스 에어리어 중에 안쪽은 베이스 에어리어로 만드는 도넛 모양을 만들어야 한다. 그다음에 맥스 에어리어일 때는 행동력을 2를 소비하도록 할 필요가 있다. 거기까지 하면 플레이어 이동 관련해서는 일단 일단락이 될 듯싶다.
voidColorPick()
{
if (tileStyle==TileStyle.Normal)
{
Gizmos.color=Color.white;
}
elseif (tileStyle==TileStyle.NonWalkable)
{
Gizmos.color=Color.red;
}
elseif (tileStyle==TileStyle.OneVigor)
{
Gizmos.color=Color.green;
}
elseif (tileStyle==TileStyle.TwoVigor)
{
Gizmos.color=Color.yellow;
}
}
일단 천천히 하나하나 해 나가자.
타일을 까는 건 보드에 있다.
voidSetTileStyle (TileNode node)
{
if (Physics.CheckSphere (node.transform.position, nodeRadius, LayerMask.GetMask ("Obstacle", "Player", "Enemy")))