로고

턴제제작 2018. 12. 1. 15:22

 이동 AI를 만들 차례인 듯싶다. 첨부터 완벽하게 커버하는 이동을 만들려고 하면 쉽지가 않으니 우선은 랜덤 한 이동을 하는 것부터 만들어야 하지 않을까 싶다.

 랜덤 한 이동을 어떻게 만들까 고민이 된다. 2단으로 이동할 수가 있지만 한번 이동할 수 있는 좌표들을 배열에 담은 다음에 그중에서 이동할 수가 없는 좌표값은 제한다. 배열 카운터 값 사이의 랜덤 한 숫자를 var로 임시로 생성을 한 다음에 해당 숫자의 배열에 못 표를 정하고 길 찾기 알고리즘을 돌려서 이동을 하면 될 듯싶다. 문득 궁금한 게 있는데 0부터 시작해야 해서 배열 카운터를 n-1을 해야 하는지 다 이것도 테스트를 해서 확인을 해봐야 할 듯싶다.

 이게 나중에 이동하고 이동하는 게 아니라 2단으로 이동할 수 있도록 하는 걸 고려할 때는 임시로 1단을 이동을 해본 다음에 판단을 내리고 아니면 처음부터 다시 판단하도록 하는 게 필요하다. 그건 차차 만들어야 할 듯싶다. 일단 랜덤으로 이동하는 것부터 만들자.

 1단계 이동 배열 값의 경우에는 원형 이동 영역을 잡고 콜라이더에 들어가는 타일들을 가져오는 걸로 하면 만들 수 있을 듯싶다.

 이동에 관해서는 우선순위로 할까 아니면 각 타일을 공식을 통해서 점수를 매기고 높은 타일을 선호하는 쪽으로 할까 고민 중이다. 일단 머 랜덤 이동부터 만들고 이문제는 차차 생각해 봐야겠다.

 오랜만에 코드를 보니까 머가 먼지 잘 모르겠다 선뜻 손이 안 간다. 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum EnemyBettleState
{
    Ready, Bettle, RunAway,
}

public class EnemyAI : MonoBehaviour {

    GameManager gameManager;

    void Awake()
    {
        gameManager = FindObjectOfType<GameManager>();
    }

    public void StartAI()
    {
        print ("Enemy AI is ready");
        var playerInfoList = FromPlayers();

playerInfoList.ForEach (i => print (i.playerPos + " : " + (int)i.distance));
    }

    public List<PlayerForEnemy> FromPlayers()
{
var infoList = new List<PlayerForEnemy>();

foreach (var player in gameManager.playerList)
{
var infoPlayer = new PlayerForEnemy();
infoPlayer.distance = Vector3.Distance (this.transform.position, player.transform.position);
infoPlayer.playerPos = player.transform.position;
infoList.Add (infoPlayer);
}

return infoList;
}
}

public class PlayerForEnemy {

public float distance;
public Vector3 playerPos;

}

 

 일단 보니까 저번에 플레이어와 거리를 검출하는 거만 만들어 놨었다. 보드 클래스로 가서 보니까 이동 가능한 타일을 담는 건 없더라. 이게 플레이랑 공통된 내용은 아니니까. 에너미 AI 쪽에다만 새로 만들면 될 듯싶다.

List<TileNode> PosibleTileOne ()
{
var newList = new List<TileNode>();

return newList;
}

 

 천리길도 한걸음부터라고 리스트를 반환하는 것부터 만들자. 이게 클릭할 때마다 var를 통해서 새 리스트를 가져와야 하는 거기 때문에 이러한 함수 형태로 만드드는 것이 좋을 듯싶다.

 이게 버그까지 잡고 다 만들고 나면 아무것도 아닌데 만들기 전에는 선뜻 손이 안 간다고 해야 하나 두려워서 회피를 하게 된다. 난생 처음 만들어 보는 거니 말이다. 그럴 땐 정말 간단한 코드 하나 만드는 것부터 천천히 시작해 나가는 게 좋다.  

 이 안에 넣어야 할 것이 에너미가 이동 가능할 영역을 배열로 담는 거다. 일단은 행동력을 1 소모하는 걸로 테스트를 배 보자.

 하이어 라키 창에 플레이어를 보니까 유틸리티에 무브 베이스 에어리어라고 되어 있는 거랑 무브 맥스 에어리어라고 되어 있는 게 있다. 이걸 에너미에서도 가져와서 등록을 해야 할 듯싶다.

 유틸리티에 무브 베이스 에어리어라고 되어 있는 오브젝트를 일단 켜서 해당 콜라이더와 겹치는 타일들을 검출해 내서 담아야 할 듯싶다. 

 3번 이동할 수도 있기 때문에 용어를 좀 변경할 필요가 있을 듯싶다.

    GameManager gameManager;
public GameObject moveBaseArea;
    public GameObject moveDoubleArea;


    void Awake()
    {
        gameManager = FindObjectOfType<GameManager>();
print (this.transform);
moveBaseArea = this.transform.Find ("Utility").Find("MoveBaseArea").gameObject;
        moveDoubleArea = this.transform.Find ("Utility").Find("MoveDoubleArea").gameObject;
    }

 

 이상한 버그가 있다. 에너미뿐만 아니라 GameManger까지 this.transform으로 인지를 해 버린다.

 원인을 찾았은데 게임 매니저에다가 EnemyAI 스크립트를 붇여 놔서 그렇더라. 이게 개별 에너미에서 작동하는 게 아니라 원래 의도가 통합 AI 시스템을 만드는 거였나 보다. 해당 함수를 여기다 만들면 안 되겠다.

    public GameObject moveBaseArea;
    public GameObject moveDoubleArea;

    public EnemyTurnState enemyTurnState = EnemyTurnState.Waiting;
    public EnemyActiveState enemyActiveState = EnemyActiveState.Ready;


    void Awake()
    {
        gameManager = FindObjectOfType<GameManager>();
        board = FindObjectOfType<Board>();
        enemyAI = FindObjectOfType<EnemyAI>();
        enemyMove = this.GetComponent<EnemyMove>();
        enemyBase = this.GetComponent<Base>();
        moveBaseArea = transform.Find ("Utility").Find("MoveBaseArea").gameObject;
        moveDoubleArea = transform.Find ("Utility").Find("MoveDoubleArea").gameObject;
    }

 

 에너미 클래스로 옮겼다.

 일단 에너미가 자동적으로 이동하는 시스템까지 만들고 유튜브에 공개해야겠다. 한 달 동안 영상을 안 올렸더니 요새 접속자도 없고 뜸하다.  다행인 게 구독자는 2명 더 늘었다.

 UI는 일단 내용은 안 채우고 외로운 울프 콘셉트로 넣어 놯아지 물론 유튜브에 올릴 때는 게임의 로고 혹은 아이고 이아를 상징하는 로고로 바꾸어서 올려야 할 듯싶다. 기본 콘셉트는 같다 동그라미 테두리 안에 특정 동물이나 인물의 특정적인 행위를 연상할 수 있는 것을 클로즈업해서 그러 넣은 거 말이다. 

 유튜브의 경우에는 영상을 자주 올려야 구독자도 확보하고 확장을 할 수가 있지만 마케팅 측면에서는 먼가 변화가 많지 않은데 자주 올리면 홍보효과가 떨어져 버린다. 가장 좋은 건 게임 제작 영상을 올리는 중간 텀에 다른 영상들을 넣어줘서 흥미를 쉽게 잃지 않도록 하는 거다. 중간중간 허튼짓하는 시간을 거기에 돌려야 하지 않을까 싶다.

 게임의 이름은 '갈라테이아'로 생각하고 있다. 이게 피그말리온이 자신의 이상형으로 조각한 게 갈라테이아다. 첨에 기획단계에서 스토리가 인셉션과 유사했었다. 주인공 팀의 수익 사업 중에는 남에 꿈에 들어가서 이상형을 바꿔치기해준다는 거였다. 안드로이드가 인간의 꿈도 조작할 수 있게 된다는 스토리라.

 근데 이게 너무 클리세스러워서 스토리를 좀 바꿀 생각이다. 

 여하튼 카메라 이동 기능도 좀 구현을 해야겠네.

 에셋을 다운로드하여서 보고 있다. 광원 때문에 360도 돌려버리면 이렇게 어두워져 보이는 문제가 있다. 전등을 하나 더 만들거나 전등도 돌아가게 수정을 해야 할 듯싶다. 또 회전을 할 때 90도가량 회전을 하게 해야 딱딱 맞아떨어질 듯싶다.

 일단 전등을 하나 더 만드는 것은 의도했던 색감이 안 나와 버려서 힘이 든다. 그냥 나도야 겠다. 씹 다크 한 것도 나름 느낌 있다. 좋아하는 사람은 그걸로 하라고 하면 되니까. 이게 엑스컴의 묘미가 카메라 화면을 돌려가면서 생각을 하는 건데 그걸로 할까 이렇게 자유롭게 돌아가는 걸로 할까 고민이 된다. 

 일단 스크롤을 당겼을 때 카메라 사이즈가 늘어났다가 줄어드는 게 작동이 잘 안 된다. 이게 Height를 손을 보게 되어 있는다 그게 아니라 내가 만들 것이 사이즈를 바꿔야 줌인 줌아웃이 되게 시스템이 짜여 있다. 그걸 손을 좀 봐야겠다.

 스튜디오 로고는 AigoiA 이걸로 정했다. 

 RTS Camera 무료 에셋에서 이런 식으로 바꿔주면 오소그래픽에서도 줌인 줌 아웃이 된다.

Camera thisCamera;
void Awake()
{
thisCamera = GetComponent<Camera>();
}

 

 
private void HeightCalculation()
{
float distanceToGround = DistanceToGround();
if(useScrollwheelZooming)
zoomPos += ScrollWheel * Time.deltaTime * scrollWheelZoomingSensitivity;
if (useKeyboardZooming)
zoomPos += ZoomDirection * Time.deltaTime * keyboardZoomingSensitivity;

zoomPos = Mathf.Clamp01(zoomPos);


float targetHeight = Mathf.Lerp(minHeight, maxHeight, zoomPos);
float difference = 0;

if(distanceToGround != targetHeight)
difference = targetHeight - distanceToGround;

m_Transform.position = Vector3.Lerp(m_Transform.position,
new Vector3(m_Transform.position.x, targetHeight + difference, m_Transform.position.z), Time.deltaTime * heightDampening);
 
thisCamera.orthographicSize = targetHeight;
}

 

 나중에 45도로 회전하는 걸 만들기로 하고 일단은 그냥 자유롭게 회전하고 줌인 줌 아웃하도록 해야겠다.

 위로 올라가는 게 잘 작동이 안돼서 문제다. 그래서 여분을 더 만들어 주었다.

Rect upRect = new Rect(0, Screen.height - screenEdgeBorder +1, Screen.width, screenEdgeBorder);

 

 모니터마다 좀 다를 수가 있으니 1픽셀 정도 여분을 만들어 둬서 문제 될 거는 없는 듯싶다.

Rect leftRect = new Rect(-1, -1, screenEdgeBorder, Screen.height);
Rect rightRect = new Rect(Screen.width - screenEdgeBorder, -1, screenEdgeBorder, Screen.height);
Rect upRect = new Rect(-1, Screen.height - screenEdgeBorder +1, Screen.width, screenEdgeBorder);
Rect downRect = new Rect(-1, -1, Screen.width, screenEdgeBorder);

 

 테스트를 해봤다. 일단 카메라 각에 따라 캐릭터가 사라져서 안 보여 버리는 버그가 있다.  보니까 카메라가 캐릭터를 비추지 않고 있다. 카메라 각을 바꾸면 거기에 맞추어서 카메라의 x좌표와 z 좌표를 설정해 줄 필요가 있는 듯싶다. 그렇다면 카메라를 돌리는 게 아니라. 카메라에서 래이케스트를 쏘고 그 지점을 중심으로 카메라가 원을 그리도록 해야 할 듯싶다. 아니면 지표면에 좌표를 만들고 카메라를 거기에 자식 노드로 설정하는 것도 하나의 방식일 듯 깇다. 여하튼 새로운 방식을 한번 실험해 보도록 하자.

 카메라를 돌릴 때 광원도 돌아가게 하면 음영이 생기는 문제는 해결되긴 하다. 이동 AI를 만들어야 한다.  카메라 연구하는데 열을 쓰는 듯싶다 이게 이동의 경우에 중심축을 움직이도록 해야겠다.

Icon.svg
다운로드
Base.svg
다운로드
Round.svg
다운로드

 디폴트 울프 아이콘은 이 파일이다. 오픈소스인데... 이게 변형해서 쓰는 경우 변형한 걸 공개해야 하는 라이선스가 걸려있다.

 지금 카메라가 아이소라 대각선으로 움직이게 되어 있으니 이걸 위아래로 움직이도록 손을 받야겠다.

 아이소가 가로가 2칸이고 위가 1칸이던가 

 아 깜박한 게 지금 이 에셋 수정하고 있는 중이다. 

 일단 이렇게 바꿔 봤다. 좌우는 문제없이 움직이는데 문제는 위아래이다

desiredMove = Quaternion.Euler(new Vector3(30f, 45f, 0f)) * desiredMove;

 

 이런 식으로 바꾸니 문제없이 잘 작동한다. 그냥 Y축만 바꾸면 되는 듯싶다.

desiredMove = Quaternion.Euler(new Vector3(0f, 45f, 0f)) * desiredMove;
 

 

 아... 카메라를 돌리면 또 이게 말을 안 듣는다. 카레라를 돌릴 때 오일러 앵글도 같이 회전을 하도록 해주어야 할 듯싶다.

desiredMove = Quaternion.Euler(new Vector3(0f, transform.eulerAngles.y + 45f, 0f)) * desiredMove;

 

 지금 어디를 수정하고 있는지 혹시 감이 안올라까. 적시한다

/// <summary>
/// move camera with keyboard or with screen edge
/// </summary>
private void Move()
{
if (useKeyboardInput)
{
Vector3 desiredMove = new Vector3(KeyboardInput.x, 0, KeyboardInput.y);

desiredMove *= keyboardMovementSpeed;
desiredMove *= Time.deltaTime;
desiredMove = Quaternion.Euler(new Vector3(0f, transform.eulerAngles.y + 45f, 0f)) * desiredMove;
desiredMove = m_Transform.InverseTransformDirection(desiredMove);

m_Transform.Translate(desiredMove, Space.Self);
}

if (useScreenEdgeInput)
{
Vector3 desiredMove = new Vector3();

Rect leftRect = new Rect(-1, -1, screenEdgeBorder, Screen.height);
Rect rightRect = new Rect(Screen.width - screenEdgeBorder, -1, screenEdgeBorder, Screen.height);
Rect upRect = new Rect(-1, Screen.height - screenEdgeBorder +1, Screen.width, screenEdgeBorder);
Rect downRect = new Rect(-1, -1, Screen.width, screenEdgeBorder);

desiredMove.x = leftRect.Contains(MouseInput) ? -1 : rightRect.Contains(MouseInput) ? 1 : 0;
desiredMove.z = upRect.Contains(MouseInput) ? 1 : downRect.Contains(MouseInput) ? -1 : 0;

desiredMove *= screenEdgeMovementSpeed;
desiredMove *= Time.deltaTime;
desiredMove = Quaternion.Euler(new Vector3(0f, transform.eulerAngles.y + 45f, 0f)) * desiredMove;
desiredMove = m_Transform.InverseTransformDirection(desiredMove);

m_Transform.Translate(desiredMove, Space.Self);
}
 
if(usePanning && Input.GetKey(panningKey) && MouseAxis != Vector2.zero)
{
Vector3 desiredMove = new Vector3(-MouseAxis.x, 0, -MouseAxis.y);

desiredMove *= panningSpeed;
desiredMove *= Time.deltaTime;
desiredMove = Quaternion.Euler(new Vector3(0f, transform.eulerAngles.y + 45f, 0f)) * desiredMove;
desiredMove = m_Transform.InverseTransformDirection(desiredMove);

m_Transform.Translate(desiredMove, Space.Self);
}
}

 

 이미 잘 만들어 놓은 다른 분의 코드를 보면서 배우는 게 많은 듯싶다. 카메라 이동 문제를 좀 해결했으니 유튜브에 한번 올리고 에너미 이동 AI를 좀 손봐야겠다. 일단 올리기 전에 울프 부분을 좀 손을 봐야 될 듯싶다. 기왕에 영상을 올리 김에 저번에 만들어 놓은 아이고 이아 로고를 올리는 게 홍보 효과도 있고 그럴 듯싶다.

 그냥 아이고 이아 로고 말고 게임 자체를 상징하는 로고를 또 따로 만들어야 할 듯싶다. 

 이게 더 분위기가 더 근사 한가... 

 색을 한번 바꿔 보자.

 내용물을 채울 거면 테두리가 있는 게 좋은 듯싶다.

색을 반전시켜 보자.

 이게 더 나은 거 같기도 하고...

 반반씩 섞어도 본다.

 일단 흰 바탕에 초록빛 도는 검정으로 정했다. 게임 로고를 만들어야 될 거 같다. 꽤 오랫동안 디폴트 UI를 사용하게 될 거 같으니 말이다.

 근데 문제는 게임 로고를 멀 어떻게 만들어야 할지 잘 모르겠다.

 일러는 그냥 유니티 쉐이더가 만들어 주는 걸 쓰는 게 생산성이 좋을 듯싶다. 얼굴 부분에 좀 어색한 부분만 손을 데었다.

 

 이런 식으로 잘라내야 할 듯싶다.

 

 사실상의 주인공인 안드로이드라 게임 이름도 갈라테이아라고 지음... 이 노래에서도 영감을 좀 얻어 왔다.

 

 

 

 

 UI 부분을 다시 보고 있다. 캐릭터를 선택하면 패시브로 어떤 스킬들이 등록이 되어 있는지를 알려 주어야 한다. 오른쪽에 얼굴과 함께 아래에 해당 스킬들이 등록이 되도록 해야 할 듯싶다. 캐릭터의 레벨과 남은 경험치도 알려 주어야 할 듯싶다. 남은 경험치가 얼마 안 남았았다면 막타 기회가 있을 때 먹도록 유도하면 좋을 테니 말이다. 캐릭터 일러를 클릭하면 자세한 캐릭터의 설명이 나오도록 패치하는 것도 좋을 듯싶다. 캐릭터가 이번에 레벨업을 하면 레벨업을 했다는 것도 알려주어야 할 듯싶다..

 일러스트에 쓰일 픽셀을 좀 규격화해서 잘라내야 유니티에 적용하기가 좀 수월하겠네. 안 그러니 늘어나고 어떻게 픽셀을 정해야 할지 감이 안 온다. 

 밑에 패시브 정보를 추가하려면 50씩 하면 4개에서 5개 최소 가로가 200 픽셀은 되어야 할 듯싶다. 액티브 스킬을 4개까지 제한하고 패시브 스킬도 4개까지 제한을 해야 될 듯싶다. 지금 아이콘 크기가 크니 말이다. 그거랑 저번에 만들어 놓은 허드를 추가해서 제한시간 같은 숫자 정보를 표시하도록 해야 한다.

 UI를 딱 적정크기로 만드는 거는 나중에 하고 일단은 이것저것 테스트를 해보는 게 더 좋은 듯싶다.

 모가 이리 어럽지.

 

 

'턴제제작' 카테고리의 다른 글

AI 이동  (0) 2018.12.08
인디게임 프로젝트 [영상]  (0) 2018.12.08
턴제 전략 [영상]  (0) 2018.11.08
AI 구상  (0) 2018.10.05
엄패  (0) 2018.09.23

WRITTEN BY
아이고이아

,