일단 적 캐릭터를 이동을 시켜야 한다. 아직 장애물이나 그런 게 많지가 않아서 굳이 은패를 더 선호하게 이동을 시킬 필요는 없는 듯싶다. 전투 시스템도 아직 제대로 짠 것도 아니고 말이다. 선행해서 만들어야 할 것들이 좀 있기 때문에 우선은 옆으로 두 칸씩 이동하는 걸 만들고 그다음에 랜덤 하게 이동을 하는 걸 만들어야 할 듯싶다. 행동력을 다 소비할 때까지 말이다. 행동력을 고려해서 이동하는 것은 전투와 관련이 있는 요소라 우선은 랜덤 하게 이동을 하고 플레이어에게 턴을 넘기는 걸로 넘어가야 될 듯싶다.
전번에 에너미 무브 클래스를 만들어 놓으니까 그거 테스트를 해봐야 할 듯싶다. 일단 에너미 턴이 되면 앞으로 2칸씩 움직이는 거를 만들어야겠다. 아 그리고 동시에 움직이는 게 아니라 순차적으로 움직이도록 해야 한다. 일단은 동시에 움직이는 것부터 구현하고 그다음으로 순차적으로 움직이는 걸 만들어야 할 듯싶다.
using System . Collections ;
using System . Collections . Generic ;
using UnityEngine ;
public class EnemyAI : MonoBehaviour {
public GameManager gameManager;
// enemyList and PlayerList are in the GameMander
void Awake ()
{
gameManager = FindObjectOfType< GameManager >();
}
public void StartAI ()
{
print ( "Enemy AI is ready" );
gameManager . enemyList .ForEach (i => i .TestMove());
}
public void TestMove ()
{
var testTile = new List < TileNode >();
enemyMove .IndicateUnit ( testTile );
}
우선 테스트 무브를 만든다. 아직은 리스트 안에 아무것도 들어가 있지가 않기 때문에 오류가 뜬다. 이동할 타일을 검색해서 타일 리스트에 넣어주어야 한다.
public void TestMove ()
{
var testTileList = new List < TileNode >();
var enemyPos = GameUtility .Coordinate ( this . transform . position );
var testTile1 = board . transform .Find ( "TileNode (" + ( enemyPos . x + 4 ) + ", " + ( enemyPos . y ) + ")" ).GetComponent< TileNode >();
var testTile2 = board . transform .Find ( "TileNode (" + ( enemyPos . x + 2 ) + ", " + ( enemyPos . y ) + ")" ).GetComponent< TileNode >();
testTileList .Add ( testTile1 );
testTileList .Add ( testTile2 );
enemyMove .IndicateUnit ( testTileList );
}
이렇게 만들면 되는데. 다만 플레이어 캐릭터 이동이 끝나기도 전에 턴이 넘어가기 때문에 플레이어와 에너미가 동시에 움직인다는 문제가 있다. 코 루틴을 써야 할 듯싶다. 어디에서 써야 하는지 고민이 된다. 이동을 마친 다음에 행동력이 줄어들게 해야 하느지도 고민이 된다.
근데 보니까 게임 매니저에서 이미 해당 기능을 만들어 놓았다. 거기서 만들어야 할 듯싶다.
void OnMouseDown ()
{
// print (this.name);
// print (this.tileStyle);
// enable moving
if ( gameManager . currentPlayer != null )
{
if (( tileStyle == TileStyle . OneVigor || tileStyle == TileStyle . TwoVigor )
&& gameManager . currentPlayer . playerTurnState == PlayerTurnState . Active && gameManager . currentPlayer . currentVigor > 0 )
{
if ( gameManager . currentPlayer . playerActiveState == PlayerActiveState . NotAnything )
{
Moving();
gameManager .SpendSkill ( Skill . Moving , this );
}
}
}
}
IEnumerator Indicator ( List < Vector3 > way)
{
// start
var destinationFlag = Instantiate ( destinationPoint , way [ way . Count - 1 ], Quaternion . identity );
enemy .GetComponent< CapsuleCollider >(). enabled = false ;
board .ResetBoard();
enemy . enemyActiveState = EnemyActiveState . Moving ;
yield return null ;
if ( way == null )
{
print ( "No Way" );
DestroyImmediate ( destinationFlag );
enemy .GetComponent< CapsuleCollider >(). enabled = true ;
board .ResetBoard();
enemy . enemyActiveState = EnemyActiveState . Ready ;
}
// do
foreach ( var destination in way )
{
MoveUnit ( destination );
while ( enemy . enemyActiveState == EnemyActiveState . Moving )
{
yield return null ;
}
}
yield return null ;
// end
DestroyImmediate ( destinationFlag );
enemy .GetComponent< CapsuleCollider >(). enabled = true ;
board .ResetBoard();
// player.activeOff.Invoke();
enemy . enemyActiveState = EnemyActiveState . Ready ;
}
코루틴을 쓰지 않고 그 해당 부분을 빌고 스킬을 사용 시 행동력을 깎는 것과 턴이 끝났을 때 행동력을 체크하는 부분을 분리하였다.
void CheckPlayerTurn ( List < Player > waitingPlayerList)
{
if ( waitingPlayerList . Count != 0 )
{
currentPlayer = waitingPlayerList [ 0 ];
SelectPlayer ( currentPlayer );
return ;
}
else
{
currentPlayer = null ;
turnState = Turn . EnemyTurn ;
print( "EnemyTurn" );
// TestEnemyAI();
enemyAI .StartAI();
return ;
}
}
public void SpendSkill ( Skill skillName, TileNode clickedTile = null )
{
if ( skillName == Skill . Moving && clickedTile != null )
{
// print (clickedTile.tileStyle);
if ( clickedTile . tileStyle == TileStyle . OneVigor )
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 1 ;
}
else if ( clickedTile . tileStyle == TileStyle . TwoVigor )
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
else
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 1 ;
}
}
else if ( skillName == Skill . Attack )
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
board .ResetBoard();
}
void CheckPlayerTurn ( List < Player > waitingPlayerList)
{
if ( waitingPlayerList . Count != 0 )
{
currentPlayer = waitingPlayerList [ 0 ];
SelectPlayer ( currentPlayer );
return ;
}
else
{
currentPlayer = null ;
turnState = Turn . EnemyTurn ;
print( "EnemyTurn" );
// TestEnemyAI();
enemyAI .StartAI();
return ;
}
}
이 문제를 해결했다. 그러나 단거리 이동에도 행동력을 2를 쓰는 버그가 아직 있다.
public void SpendSkill ( Skill skillName, TileNode clickedTile = null )
{
if ( skillName == Skill . Moving && clickedTile != null )
{
// print (clickedTile.tileStyle);
if ( clickedTile . tileStyle == TileStyle . OneVigor )
{
print ( "One Vigor" );
currentPlayer . currentVigor = currentPlayer . currentVigor - 1 ;
}
else if ( clickedTile . tileStyle == TileStyle . TwoVigor )
{
print ( "Two Viger" );
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
}
else if ( skillName == Skill . Attack )
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
board .ResetBoard();
}
해당 문제도 해결했다.
그러나 여전히 문제가 있다. 한 칸을 움직인 다음에는 이동 가능 범위를 한 칸 범위로 줄여야 한다. 행동력이 -1이 가능하기 때문에 1 행동력 범위를 이동하고 2 행동력 범위로 움직이게 할 수 있는 문제가 있다.
보드 클래스에 이 부분을 좀 수정하면 될 듯싶지 않나 싶다. 지금은 행동력이 몇이든 일괄적으로 키고 있으니 말이다.
void MoveAreaOn ()
{
if ( gameManager . currentPlayer != null )
{
if ( gameManager . currentPlayer . currentVigor == 2 )
{
gameManager . currentPlayer . moveMaxArea .SetActive ( true );
gameManager . currentPlayer . moveBaseArea .SetActive ( true );
}
else if ( gameManager . currentPlayer . currentVigor == 1 )
{
gameManager . currentPlayer . moveMaxArea .SetActive ( false );
gameManager . currentPlayer . moveBaseArea .SetActive ( true );
}
else if ( gameManager . currentPlayer . currentVigor <= 0 )
{
gameManager . currentPlayer . moveMaxArea .SetActive ( false );
gameManager . currentPlayer . moveBaseArea .SetActive ( false );
}
}
}
이런 식으로 바꾸었더니 해당 문제가 해결이 되었다.
여전히 독특한 버그가 있다. 이동이 끝나기 전에 다른 캐릭터를 이동할 수 있도록 편의를 제공했더니 커런트 플레이어가 바뀌는 통에 플레이어의 턴 종료가 인지가 안 되는 문제가 있다. 좀 고차원 적인 버그라고 해야 하나.
public void CheckPlayerTurn ()
{
if ( currentPlayer . currentVigor <= 0 )
{
var waitingPlayerList = new List < Player >();
foreach ( var player in playerList )
{
if ( player . playerTurnState == PlayerTurnState . Waiting )
{
waitingPlayerList .Add ( player );
}
}
if ( waitingPlayerList . Count != 0 )
{
currentPlayer = waitingPlayerList [ 0 ];
SelectPlayer ( currentPlayer );
return ;
}
else
{
currentPlayer = null ;
turnState = Turn . EnemyTurn ;
print( "EnemyTurn" );
// TestEnemyAI();
enemyAI .StartAI();
return ;
}
}
}
}
public void CheckVigor ()
{
// print ("Check Vigor");
if ( currentPlayer . currentVigor <= 0 )
{
currentPlayer . playerTurnState = PlayerTurnState . Ending ;
print ( currentPlayer . name + " is end" );
currentPlayer . activeOff .Invoke();
}
}
IEnumerator Indicator ( List < Vector3 > way)
{
// start
player . playerActiveState = PlayerActiveState . Moving ;
var destinationFlag = Instantiate ( destinationPoint , way [ way . Count - 1 ], Quaternion . identity );
player .GetComponent< CapsuleCollider >(). enabled = false ;
board .ResetBoard();
yield return null ;
if ( way == null )
{
print ( "No Way" );
DestroyImmediate ( destinationFlag );
player .GetComponent< CapsuleCollider >(). enabled = true ;
board .ResetBoard();
player . playerActiveState = PlayerActiveState . NotAnything ;
}
// do
foreach ( var destination in way )
{
MoveUnit ( destination );
while ( player . playerActiveState == PlayerActiveState . Moving )
{
yield return null ;
}
}
yield return null ;
// end
DestroyImmediate ( destinationFlag );
player .GetComponent< CapsuleCollider >(). enabled = true ;
board .ResetBoard();
// player.activeOff.Invoke();
player . playerActiveState = PlayerActiveState . NotAnything ;
gameManager .CheckPlayerTurn();
}
void OnMouseDown ()
{
// print (this.name);
// print (this.tileStyle);
// enable moving
if ( gameManager . currentPlayer != null )
{
if (( tileStyle == TileStyle . OneVigor || tileStyle == TileStyle . TwoVigor )
&& gameManager . currentPlayer . playerTurnState == PlayerTurnState . Active && gameManager . currentPlayer . currentVigor > 0 )
{
if ( gameManager . currentPlayer . playerActiveState == PlayerActiveState . NotAnything )
{
Moving();
}
}
}
}
public void SpendSkill ( Skill skillName, TileNode clickedTile = null )
{
if ( skillName == Skill . Moving && clickedTile != null )
{
// print (clickedTile.tileStyle);
if ( clickedTile . tileStyle == TileStyle . OneVigor )
{
print ( "One Vigor" );
currentPlayer . currentVigor = currentPlayer . currentVigor - 1 ;
}
else if ( clickedTile . tileStyle == TileStyle . TwoVigor )
{
print ( "Two Viger" );
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
}
else if ( skillName == Skill . Attack )
{
currentPlayer . currentVigor = currentPlayer . currentVigor - 2 ;
}
board .ResetBoard();
CheckVigor();
}
public void CheckVigor ()
{
// print ("Check Vigor");
if ( currentPlayer . currentVigor <= 0 )
{
currentPlayer . playerTurnState = PlayerTurnState . Ending ;
print ( currentPlayer . name + " is end" );
currentPlayer . activeOff .Invoke();
}
}
생각보다 많은 부분을 고쳤다. 문제는 다시 이동이 끝나지 않았다. 에너미 턴이 시작되는 문제가 제발 한다는 거다.
public void CheckPlayerTurn ()
{
if ( currentPlayer == null ) {
return ;
}
if ( currentPlayer . currentVigor > 0 )
{
return ;
}
var waitingPlayerList = new List < Player >();
foreach ( var player in playerList )
{
if ( player . playerTurnState == PlayerTurnState . Waiting )
{
waitingPlayerList .Add ( player );
}
}
if ( waitingPlayerList . Count != 0 )
{
currentPlayer = waitingPlayerList [ 0 ];
SelectPlayer ( currentPlayer );
return ;
}
else
{
currentPlayer = null ;
turnState = Turn . EnemyTurn ;
print( "EnemyTurn" );
// TestEnemyAI();
enemyAI .StartAI();
return ;
}
}
이런 식으로 바꿔주면 문제가 해결된다가 아니라. 이게 중간쯤 해서 문직이기 시작한다. 완전히 도착하고 움직여야 할 텐데 말이다. 한 행동력만 쓸 때는 문제가 없다. 두 행 동력을 이동할 때 한 행 동력 이동 한 다음 중간쯤에 서 턴이 넘어가 버린다.
이게 아마 1번 캐릭터의 동작이 끝난 시점에서 2번 캐릭터는 이동을 하고 있지만 1번 캐릭터에서 턴 체크를 했을 때 이미 행동력을 써버린 상황이어서 그런 듯싶다.
public void CheckPlayerTurn ()
{
if ( currentPlayer == null ) {
return ;
}
if ( currentPlayer . currentVigor > 0 )
{
return ;
}
foreach ( var player in playerList )
{
if ( player . playerActiveState == PlayerActiveState . Moving )
{
return ;
}
}
var waitingPlayerList = new List < Player >();
foreach ( var player in playerList )
{
if ( player . playerTurnState == PlayerTurnState . Waiting )
{
waitingPlayerList .Add ( player );
}
}
if ( waitingPlayerList . Count != 0 )
{
currentPlayer = waitingPlayerList [ 0 ];
SelectPlayer ( currentPlayer );
return ;
}
else
{
currentPlayer = null ;
turnState = Turn . EnemyTurn ;
print( "EnemyTurn" );
// TestEnemyAI();
enemyAI .StartAI();
return ;
}
}
}
이걸 이렇게 해주면 된다. 허허허... 이제 더는 버그가 없어야 할 텐데...