1.Tiny Island Project?

  • 일단 모바일 게임 프로젝트이다. AOS/iOS 모두 출시예정이다
  • 모바일게임 특성상 조작이 불편하기에 한손조작을 택했다.
  • 내가 좋아하는 콘솔게임은 거의 위쳐/젤다의전설과같은 스토리가 가미된 RPG게임이라고 정리할수있다. 모바일게임은 정말 왠만해서는 즐겨하지않기에 나도 즐길수있는 모바일게임을 목표로 만들기시작한다.
  • 스토리는 다크소울이나 블러드본과같이 불친절한 스토리보다는 선형적이고 쉬운 스토리가 좋더라. 메인스토리는 굵고 진하게 있으면서 서브스토리에서 자유도를 주는게 내 취향이기에 요렇게 만들어보고자한다.
  • 개발지향성은 가볍게 빨리 만들어서 빠르게 출시하자인데, 요건 조금 오래걸릴것같긴하다. RPG를 만든다는건 진짜 어려운일이다.
    • 아트스타일은 스타일이라고 할것도없다. 거의 에셋스토어에서 구매해서 조정하는식으로 가야할것같다. 다음번에는 2D 도트스프라이트를 도전하기로하고 이번에는 꼭 해보고싶어서 계속 도전했지만 매번 접었던 3D 로우폴리곤 스타일 게임을 만들어보고자한다.

2.진척사항은?

  • 2020년 6월 현재, 프로젝트생성한지는 두달정도된것같다. 겁나빠르네
  • 현재 유니티 기본터레인으로 가장 기본이되는 섬을 60%정도 만들었다.
  • Triplanar Shader를 통해 절벽과 평지를 자연스럽게 블렌딩하게하고, 터레인 모델링이 완성되면 이를 mesh로 변환하여 유니티 polybrush를 통해 버텍스컬러를 칠해서 평지의 길등을 블렌딩하려고 한다.

기본 세로 한손모드로 섬에서 펼쳐지는 이야기

현재개발스크린샷. 섬에서 펼쳐지는 이야기.


  • grass도 잘 넣고싶은데 지오메트리쉐이더를 통해서 풀을 만들고싶었는데 ios metal에서는 이 쉐이더가 작동이 안되는것같다.. 결국 그냥 mesh를 c#에서 조정해서 만들어봤다. 요건 계속 조정해봐야할듯.
  • 캐릭터 이동은 에셋스토어에서 사서 써봤다. 게속 캐릭터컨트롤러 혼자서 만들어서 썼었는데 굴곡있는 지형에서 갑자기 뚫고내려간다던가, 경사에서 붙어버린다던가 하는 버그가 계속있어서 스트레스.. 역시 잘만든 코드 가져다 쓰는게 최고긴하다. 잘된다. 나중에 요 코드 공부해서 내것으로 만들긴해야지. (사용한 에셋은 다음과같다:Character Controller Fundamentals)
  • 카메라 워크는 역시 유니티에서 제공하는 시네머신을 사용했다. 빠르게 만드는게 중요하다.

모델링도 커스터마이징이 필요하다

모델링도 커스터마이징해야한다. 일단synty studio 에서 받은 에셋을 사용중이다

3.해야할것들

아직 엄청 많다. 큰 골격으로 조만간해야할것들은 다음과같다.

  1. 기본적인 전투기획. 어떻게 공격하고 회피하고 할지 정하지못했다.
  2. 적 AI구현. 일단 단순 스테이트머신이아니라 행동트리로 구현하기로 결정.
  3. 퀘스트 구조 짜기.
  4. 컷씬 및 이벤트 관련 매니저.
  5. 아트적인건 거의 다 스토어에서 살거긴하지만, 조금씩 조정하려면..

암튼 엄청 많다. 몇달은 걸릴것같은 장기프로젝트이다. 다음달에 각을 봐서 프로토타입을 일단 만들고 출시일을 설정해야겠다.

4.오늘 한것.

  • 오늘은 데이터 매니저를 만들었다.
  • 기본적으로 게임데이터를 파일에 쓰고 읽는 역할과 씬간 이동시 데이터를 가지고있는 매니저이다.
  • 씬전환시 모든 데이터를 세이브하고 씬로드후에 다시 모든데이터를 로드하며, 파일로 쓰고 읽는건 Easy Save 에셋을 활용하였다. 데이터클래스들은 interface를 상속하였고 이 인터페이스들을 데이터매니저가 hashset/dictionary로 관리한다. 유니티 2d kit 코드를 많이 참고하였다.

관련 코드예제.

public interface IStayableData
{
    DataSetting GetDataSetting();

    void SetDataSetting(string dataTag, DataSetting.DataPermission permissionType);

    Data SaveData();

    void LoadData(Data data);

  
}

public class Data 
{
    
}

public class Data<T> : Data
{
    public T value;

    public Data(T value)
    {
        this.value = value;
    }
        
}


public class DataManager : SingletonBase<DataManager> {


    private Dictionary<string, Data> dicData = new Dictionary<string, Data>();
    private HashSet<IStayableData> hsStaybleData = new HashSet<IStayableData>();

    protected override void Awake()
    {
        base.Awake();
        if (Instance != this)
        {
            Destroy(this.gameObject);
            return;

        }

        DontDestroyOnLoad(this.gameObject);
    }

    public void Register(IStayableData data)
    {
        if (!string.IsNullOrEmpty(data.GetDataSetting().dataTag))
        {
            hsStaybleData.Add(data);
        }
    }

    public void UnRegister(IStayableData data)
    {
        hsStaybleData.Remove(data);
    }

    public void ClearRegisers()
    {
        hsStaybleData.Clear();
    }

    public void SaveAllData()
    {
        foreach(var data in hsStaybleData)
        {
            SaveData(data);
        }
    }

    private void SaveData(IStayableData data)
    {
        if (data.GetDataSetting().dataPermission == DataSetting.DataPermission.ReadOnly)
            return;

        dicData[data.GetDataSetting().dataTag] = data.SaveData();
    }

    public void LoadAllData()
    {
        foreach (var data in hsStaybleData)
        {
            if (data.GetDataSetting().dataPermission == DataSetting.DataPermission.WriteOnly)
                continue;
            
            if(dicData.ContainsKey(data.GetDataSetting().dataTag)){
                Debug.Log(data.GetDataSetting().dataTag);
                data.LoadData(dicData[data.GetDataSetting().dataTag]);
            }
           
        }
    }

    public void SavePlayerDataAtFile(int fileNum)
    {
        SaveAllData();

        if(dicData.ContainsKey("Player"))
        {
                       Data<PlayerData> playerData=(Data<PlayerData>)dicData["Player"];

            ES3.Save<PlayerData>("PlayerData", playerData.value, "Save/testPlayer.txt");

        }

    }
    public void LoadPlayerDataFromFile(int fileNum)
    {
        
        Data<PlayerData> playerData = new Data<PlayerData> (ES3.Load<PlayerData>("PlayerData", "Save/testPlayer.txt"));
        dicData["Player"] = playerData;

    }

댓글남기기