[NDC_16] 캐릭터 한 달에 하나씩 업데이트 하기 : '최강의 군단' 스킬 개발 툴 포스트 모템과 차기작 '건파이트 맨션' 툴 프리뷰승민 백
NDC 2016 발표 자료입니다
아래는 공개된 세션의 소개입니다
------------------------------------------------------------
게임을 개발하다 보면 액션, RPG를 비롯한 많은 장르에서 캐릭터의 스킬을 만들어야 하는 때가 옵니다.
다양한 스킬의 기획을 제한하지 않으면서도, 빠르게 개발한다는 두 가지 목표를 달성하기 위해서는 어떻게 개발해야 하는지 고민하고 프로젝트에 적용한 결과를 공유하는 세션입니다.
다음과 같은 세 가지 개발 방법을 보여드리고, 각각의 장단점을 비교하는 형태로 진행됩니다.
1. 고전적인 하드 코딩 방식
2. 한 달에 하나씩의 캐릭터 업데이트를 단행했던 <최강의>에서 사용했던 스킬 툴 방식 (온라인 액션RPG, 언리얼3 기반)
3. 현재 개발 중인 모바일 프로젝트 <건파이트>에서 시도하고 있는 언리얼4 블루프린트 기반 방식
시스템 디자인을 시작해보려는 또는 이제 막 시작한 게임 디자인 지망생 및 주니어 게임 기획자들에게 도움이 됐으면 하는 마음에 작성했습니다.
목차
1. 시스템이란?
2. 시스템 디자인에서 중요한 것
3. 시스템과 콘텐츠의 구분
4. 시스템 디자인, 왜 어렵나?
5. 나도 한번 해보자, 시스템 디자인
6. 좋은 시스템이란?
7. 주의사항
저는 운 좋게도 게임 PD로서 지난 10년 동안 몇 개의 게임을 개발하고, 서비스하는 경험을 가질 수 있었습니다.
본 세션에서는 제가 그동안 개발했던 게임들을 간단히 돌아보고, 개발 과정에서 시행착오를 통해 배운 것들을 살펴보려고 합니다.
개인적인 경험이라 편향이 있을 수 있겠지만, 게임 PD나 디렉터 커리어를 목표로 하시는 분들께 참고가 될 수 있으면 좋겠습니다.
<쿠키런:오븐브레이크> 길드탐험 및 방랑박쥐상점 컨텐츠 역기획서 (작업일자: 2019. 06. 11)
※ 해당 기획서에 작성되어 있는 일부 수치 및 확률은 실제 게임 내부와 다르며, 역기획 과정에서 기준을 세워 재계산 하였습니다.
※ <쿠키런 : 오븐브레이크>의 길드 컨텐츠중 일부만을 다루므로, 게임 내 자세히 공개되지 않는 내용이나 도움말 추가 등 일부 기획 내용은 추가되거나 변형하였습니다.
※일부 내용은 실제 팀 내부에서 개발 프로세스 진행 시 검토해야 할 것을 가정하여 작성하였습니다.
※ UI 명세 부분의 붉은 색 사선의 ‘Safe Area’는 모바일 환경 iPhone X시리즈의 UI를 고려하였습니다.
[NDC_16] 캐릭터 한 달에 하나씩 업데이트 하기 : '최강의 군단' 스킬 개발 툴 포스트 모템과 차기작 '건파이트 맨션' 툴 프리뷰승민 백
NDC 2016 발표 자료입니다
아래는 공개된 세션의 소개입니다
------------------------------------------------------------
게임을 개발하다 보면 액션, RPG를 비롯한 많은 장르에서 캐릭터의 스킬을 만들어야 하는 때가 옵니다.
다양한 스킬의 기획을 제한하지 않으면서도, 빠르게 개발한다는 두 가지 목표를 달성하기 위해서는 어떻게 개발해야 하는지 고민하고 프로젝트에 적용한 결과를 공유하는 세션입니다.
다음과 같은 세 가지 개발 방법을 보여드리고, 각각의 장단점을 비교하는 형태로 진행됩니다.
1. 고전적인 하드 코딩 방식
2. 한 달에 하나씩의 캐릭터 업데이트를 단행했던 <최강의>에서 사용했던 스킬 툴 방식 (온라인 액션RPG, 언리얼3 기반)
3. 현재 개발 중인 모바일 프로젝트 <건파이트>에서 시도하고 있는 언리얼4 블루프린트 기반 방식
시스템 디자인을 시작해보려는 또는 이제 막 시작한 게임 디자인 지망생 및 주니어 게임 기획자들에게 도움이 됐으면 하는 마음에 작성했습니다.
목차
1. 시스템이란?
2. 시스템 디자인에서 중요한 것
3. 시스템과 콘텐츠의 구분
4. 시스템 디자인, 왜 어렵나?
5. 나도 한번 해보자, 시스템 디자인
6. 좋은 시스템이란?
7. 주의사항
저는 운 좋게도 게임 PD로서 지난 10년 동안 몇 개의 게임을 개발하고, 서비스하는 경험을 가질 수 있었습니다.
본 세션에서는 제가 그동안 개발했던 게임들을 간단히 돌아보고, 개발 과정에서 시행착오를 통해 배운 것들을 살펴보려고 합니다.
개인적인 경험이라 편향이 있을 수 있겠지만, 게임 PD나 디렉터 커리어를 목표로 하시는 분들께 참고가 될 수 있으면 좋겠습니다.
<쿠키런:오븐브레이크> 길드탐험 및 방랑박쥐상점 컨텐츠 역기획서 (작업일자: 2019. 06. 11)
※ 해당 기획서에 작성되어 있는 일부 수치 및 확률은 실제 게임 내부와 다르며, 역기획 과정에서 기준을 세워 재계산 하였습니다.
※ <쿠키런 : 오븐브레이크>의 길드 컨텐츠중 일부만을 다루므로, 게임 내 자세히 공개되지 않는 내용이나 도움말 추가 등 일부 기획 내용은 추가되거나 변형하였습니다.
※일부 내용은 실제 팀 내부에서 개발 프로세스 진행 시 검토해야 할 것을 가정하여 작성하였습니다.
※ UI 명세 부분의 붉은 색 사선의 ‘Safe Area’는 모바일 환경 iPhone X시리즈의 UI를 고려하였습니다.
1. 맵 에디터 제작하기
Copyright ⓒ 2014 Unity Technologies Korea All rights reserved. All contents cannot be copied without permission
중급
본 교재의 저작권은 유니티테크놀로지스코리아가 소유하고 있으며,
유니티 러닝센터 수강생만 교재를 볼 수 있습니다. 정당한 권리 없이 저작물을 복제, 젂송할 경우
그로 인하여 발생하는 손해를 배상하여야 함을 유념하시기 바랍니다.
2. 타일 정보 구현하기
타일 편집 툴 구현하기
경로 설정용 Path툴 구현하기
맵 데이터 저장/로드 하기
3. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
디펜스 게임에서 타일이 가져야 할 정보들
1. 타일을 표현하는 이미지 정보
2. 타일의 속성(적이 이동하는 길인가?, 타워를 설치할 수 있는 위치인가?
3. 경로와 관련된 정보(시작 위치 및 목적 위치 그리고 이동 해야 할 위치)
4. 특수한 능력을 가지는 타일
타일은 적의 시작위치와, 끝 위치 그리고 경로를 표현해야 한다.
또한 경로가 아닌 곳을 표현할 수 있어야 한다.
타워는 경로가 아닌 곳에 설치할 수 있다.
4. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
게임에서 사용할 타일의 종류
5. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
5가지 타일을 이용하여 표현한 디펜스 게임의 경로
6. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
이미지가 가짂 정보를 저장하기 위해 [ TILESTYLE ] 열거형을 Enum.cs 파일에 선언
using UnityEngine;
using System.Collections;
public enum TILESTYLE
{
NORMAL = 0,
STRAIGHT,
CORNER,
START,
END,
}
7. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
타일의 정보를 적용하기 위해 [ TileInfo ] 스크립트를 생성 후 구현
using UnityEngine;
using System.Collections;
public class TileInfo : MonoBehaviour
{
public TILESTYLE currentTileStyle;
public Material[] tileMaterials;
public void UpdateMaterial()
{
renderer.material = tileMaterials[ (int)currentTileStyle ];
}
}
8. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
[ 직선타일 ] 이미지를 넣었을 때의 상황
9. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
[ TileInfo ] 스크립트를 tile 프리팹에 추가하고 마테리얼 5종 생성 후
이름을 다음과 같이 설정
10. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
[ TILESTYLE ] 순서에 맞게 [ Tile Materials ]에 마테리얼 설정
using UnityEngine;
using System.Collections;
public enum TILESTYLE
{
NORMAL = 0,
STRAIGHT,
CORNER,
START,
END,
}
11. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
[ MapManagerInspector ] 클래스의 [ CreateTiles ] 함수 부분에 기능 추가
public class MapManagerInspector : Editor
{
......
public void CreateTiles(MapManager mapManager)
{
......
for (int i = 0; i < width; ++i)
{
for (int j = 0; j < height; ++j)
{
......
TileInfo tileInfo = mapManager._tiles[ i, j ].GetComponent<TileInfo>();
tileInfo.UpdateMaterial();
}
}
}
}
12. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
[ Tile ] 프리팹에 있는 Current Tile Style의 값을 ‘STRAIGHT’로 교체
타일 정보 구현하기
13. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 정보 구현하기
14. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 편집 툴 구현하기
[ MapManager ] 클래스에 [ _editTileStyle ] 변수 추가
using UnityEngine;
using System.Collections;
public class MapManager : MonoBehaviour
{
public TILESTYLE _editTileStyle = TILESTYLE.NORMAL;
......
}
15. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 편집 툴 구현하기
[CustomEditor(typeof(MapManager))]
public class MapManagerInspector : Editor
{
......
public void OnSceneGUI()
{
if( Application.isPlaying )
return;
MapManager mapManager = target as MapManager;
Handles.BeginGUI();
if (GUI.Button(new Rect(10, 10, 100, 30), "Normal"))
{
mapManager._editTileStyle = TILESTYLE.NORMAL;
}
if (GUI.Button(new Rect(10, 50, 100, 30), "Straight"))
{
mapManager._editTileStyle = TILESTYLE.STRAIGHT;
}
if (GUI.Button(new Rect(10, 90, 100, 30), "Corner"))
{
mapManager._editTileStyle = TILESTYLE.CORNER;
}
if (GUI.Button(new Rect(10, 130, 100, 30), "Start"))
{
mapManager._editTileStyle = TILESTYLE.START;
}
if (GUI.Button(new Rect(10, 170, 100, 30), "End"))
{
mapManager._editTileStyle = TILESTYLE.END;
}
GUI.color = Color.green;
GUI.Label(new Rect(120, 10, 500, 30),
"Edit Mode : " + mapManager._editTileStyle);
GUI.color = Color.white;
Handles.EndGUI();
}
}
16. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
[ MapManager ]를 선택하면 구현한 내용이 반영되어 GUI가 씬 뷰에 출력되는 것 확인
타일 편집 툴 구현하기
17. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
특정 타일을 오른쪽 버튺 클릭 후 회젂하기 위해 타일 프리팹에 레이 케스팅에 의한
충돌검출을 하기 위한 박스 충돌체(Box Collider)를 추가
타일 편집 툴 구현하기
18. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
씬에 배치된 [ SpaceFloor ] 오브젝트에 붙어있는 박스 충돌체는 제거한 후,
씬 뷰에서 오브젝트 선택 후 타일 값을 변경하는 코드를 구현
타일 편집 툴 구현하기
[CustomEditor(typeof(MapManager))]
public class MapManagerInspector : Editor
{
......
public void OnSceneGUI()
{
......
Event e = Event.current;
if( e.type == EventType.mouseDown )
{
Vector2 mousePosition = e.mousePosition;
Ray ray =
HandleUtility.GUIPointToWorldRay( mousePosition );
RaycastHit hit;
bool result = Physics.Raycast(ray, out hit, 1000.0f);
if (result)
{
GameObject tileObj = hit.transform.gameObject;
TileInfo tileInfo = tileObj.GetComponent<TileInfo>();
if( tileInfo == null )
return;
if (e.button == 0) // left click button
{
tileInfo.currentTileStyle = mapManager._editTileStyle;
tileInfo.UpdateMaterial();
}
else if (e.button == 1) // right click button
{
hit.transform.localEulerAngles +=
new Vector3( 0.0f, 90.0f, 0.0f );
}
}
}
}
}
19. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
인스펙터 뷰의 잠김 상태 확인
타일 편집 툴 구현하기
20. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일 편집 기능으로 생성한 레벨의 모습
타일 편집 툴 구현하기
21. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
마우스 드래그로 변경할 수 있도록 구현
타일 편집 툴 구현하기
[CustomEditor(typeof(MapManager))]
public class MapManagerInspector : Editor
{
......
public void OnSceneGUI()
{
......
int controlID = GUIUtility.GetControlID(FocusType.Passive);
HandleUtility.AddDefaultControl( controlID );
Event e = Event.current;
if( e.type == EventType.mouseDown || e.type == EventType.mouseDrag )
{
if ( e.alt )
{
return;
}
......
} // End of OnSceneGUI
}
22. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
키보드 3~7번까지의 키를 눌렀을 때 타일의 정보가 변경되도록 구현
타일 편집 툴 구현하기
[CustomEditor(typeof(MapManager))]
public class MapManagerInspector : Editor
{
......
public void OnSceneGUI()
{
......
Event e = Event.current;
if( e.isKey )
{
if (e.character == ‘3') mapManager._editTileStyle = TILESTYLE.NORMAL;
else if (e.character == ‘4') mapManager._editTileStyle = TILESTYLE.STRAIGHT;
else if (e.character == ‘5') mapManager._editTileStyle = TILESTYLE.CORNER;
else if (e.character == ‘6') mapManager._editTileStyle = TILESTYLE.START;
else if (e.character == ‘7') mapManager._editTileStyle = TILESTYLE.END;
}
if( e.type == EventType.mouseDown || e.type == EventType.mouseDrag )
{
......
}
}
23. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로 설정용 Path툴 구현하기
[ MapManager ] 클래스에 다음과 같이 선언
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MapManager : MonoBehaviour
{
......
public List<Transform> _pathList = new List<Transform>();
}
24. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
Shift 버튺을 누르고 있는 상태로 마우스 클릭을 하면 경로를 추가/삭제 기능 구현
경로 설정용 Path툴 구현하기
......
public void OnSceneGUI()
{
......
Event e = Event.current;
if( e.type == EventType.mouseDown ||
e.type == EventType.mouseDrag )
{
......
if( e.button == 0 ) // left click button
{
if( e.shift )
{
if (mapManager._pathList.Contains( hit.transform ) == false)
mapManager._pathList.Add( hit.transform );
}
else
{
tileInfo.currentTileStyle = mapManager._editTileStyle;
tileInfo.UpdateMaterial();
}
}
else if( e.button == 1 ) // right click button
{
if (e.shift)
{
if (mapManager._pathList.Contains( hit.transform ) == true)
mapManager._pathList.Remove( hit.transform );
}
else
{
if( e.type == EventType.mouseDown )
hit.transform.localEulerAngles +=
new Vector3( 0.0f, 90.0f, 0.0f );
}
}
......
}
}
25. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
맵을 제거할 때 Path도 제거되도록 구현
경로 설정용 Path툴 구현하기
public class MapManager : MonoBehavior
{
......
public void RemoveAllTiles()
{
......
_pathList.Clear();
}
......
}
26. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로 설정용 Path툴 구현하기
경로의 흐름을 파악할 수 있도록 시각적인 표현을 위한 구현
......
public void OnSceneGUI()
{
MapManager mapManager = target as MapManager;
......
DrawPathList( mapManager );
}
void DrawPathList(MapManager mapManager)
{
for (int i = 0; i < mapManager._pathList.Count; ++i)
{
Transform obj = mapManager._pathList[i];
TileInfo tileInfo = obj.GetComponent<TileInfo>();
if ( tileInfo.currentTileStyle == TILESTYLE.START )
{
Handles.color = Color.green;
}
else if ( tileInfo.currentTileStyle == TILESTYLE.END )
{
Handles.color = Color.red;
}
Handles.SphereCap( i, obj.position + Vector3.up * 0.5f, obj.rotation, 0.5f );
Handles.color = Color.white;
} // End of for (… )
if (mapManager._pathList.Count > 1)
{
Handles.color = Color.magenta;
for (int i = 0; i < mapManager._pathList.Count – 1 ; ++i)
{
Transform obj1 = mapManager._pathList[i];
Transform obj2 = mapManager._pathList[i + 1];
Vector3 pos1 = obj1.position + Vector3.up * 0.5f;
Vector3 pos2 = obj2.position + Vector3.up * 0.5f;
Handles.DrawLine( pos1, pos2 );
}
Handles.color = Color.white;
}
}
27. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로 설정용 Path툴 구현하기
시각적으로 표현된 경로 흐름
28. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
인스펙터 뷰에서의
데이터 확인을 위한 구현
경로 설정용 Path툴 구현하기
public class MapManagerInspector : Editor
{
public override void OnInspectorGUI()
{
MapManager mapManager = target as MapManager;
......
CommonEditorUi.DrawSeparator(Color.cyan);
DrawPathData(mapManager);
CommonEditorUi.DrawSeparator(Color.cyan);
ShowTiles(mapManager);
}
void DrawPathData( MapManager mapManager )
{
if (GUILayout.Button("Remove All Path Data"))
{
mapManager._pathList.Clear();
}
string pathLabel = "Path List : " + mapManager._pathList.Count;
EditorGUILayout.LabelField( pathLabel );
for (int i = 0; i < mapManager._pathList.Count; ++i)
{
string pathName = "Path Index : " + i;
Transform pathTransform = mapManager._pathList[i];
EditorGUILayout.ObjectField(pathName, pathTransform,
typeof(GameObject));
}
}
}
29. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
PathData 정보 확인
경로 설정용 Path툴 구현하기
30. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
맵 데이터 저장/로드 하기
[ MapManager ] 클래스에 맵 데이터를 저장할 때 사용할
파일의 이름의 string 변수 선언
public class MapManager : MonoBehaviour
{
......
public string _fileName = "Map";
}
31. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
저장할 파일 이름을 편집할 수 있는 문자열 편집 기능과 저장/읽기 버튺 구현
맵 데이터 저장/로드 하기
public class MapManagerInspector : Editor
{
public override void OnInspectorGUI()
{
MapManager mapManager = target as MapManager;
......
DrawGenerateButton(mapManager);
CommonEditorUi.DrawSeparator(Color.cyan);
DrawSaveLoadButton(mapManager);
......
}
void DrawSaveLoadButton( MapManager mapManager )
{
string fileName = EditorGUILayout.TextField("Map File Name",
mapManager._fileName);
if (fileName != mapManager._fileName)
{
CommonEditorUi.RegisterUndo("Map File Name", mapManager);
mapManager._fileName = fileName;
}
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Save Map Data"))
{
//Save Process
}
if (GUILayout.Button("Load Map Data"))
{
// Load Process
}
EditorGUILayout.EndHorizontal();
}
}
32. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
맵 데이터 저장/로드 하기
……
using System.IO;
public class MapManagerInspector : Editor
{
......
void DrawSaveLoadButton( MapManager mapManager )
{
......
if( GUILayout.Button("Save Map Data") )
{
string title = "Save Map File‚;
string msg = ‚Do you want to save map data?‚;
if (EditorUtility.DisplayDialog(title , msg, "yes", "no") == false)
return;
string dataPath = Application.dataPath;
string fullPath = dataPath + "/Resources/MapData/" +
fileName + ".txt";
FileStream fs = new FileStream(fullPath, FileMode.Create);
TextWriter textWriter = new StreamWriter(fs);
int width = mapManager._currentWidth;
int height = mapManager._currentHeight;
textWriter.Write("width " + width + "n");
textWriter.Write("height " + height + "n");
for (int i = 0; i < width; ++i)
{
for (int j = 0; j < height; ++j)
{
Transform tile = mapManager._tiles[i, j].transform;
textWriter.Write(tile.position + "t");
textWriter.Write(tile.eulerAngles + "t");
TileInfo tileInfo = tile.GetComponent<TileInfo>();
textWriter.Write((int)tileInfo.currentTileStyle + "t");
textWriter.Write("n");
}
} // End of for( int i = 0 ...
// save path
int pathCount = mapManager._pathList.Count;
textWriter.Write("PathCount " + pathCount + "n");
for (int i = 0; i < pathCount; ++i)
{
string[] tileIndex = mapManager._pathList[i].name.Split('_');
textWriter.Write(tileIndex[0] + "t");
textWriter.Write(tileIndex[1]);
textWriter.Write("n");
}
textWriter.Close();
} // End of if( GUILayout.Button("Save Map Data") )
} // End of void DrawSaveLoadButton
33. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
파일 저장 구현
- 앆젂장치구현
맵 데이터 저장/로드 하기
public class MapManagerInspector : Editor
{
......
void DrawSaveLoadButton( MapManager mapManager )
{
......
if( GUILayout.Button("Save Map Data") )
{
……
textWriter.Close();
string backupPath = dataPath + "/Resources/MapData/" +
fileName + "_backup.txt";
if( File.Exists(backupPath) == false )
FileUtil.CopyFileOrDirectory(fullPath, backupPath);
AssetDatabase.Refresh();
}
// End of if( GUILayout.Button("Save Map Data") )
} // End of void DrawSaveLoadButton
34. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
파일을 저장될 [ Resources/MapData ] 폴더는 미리 생성해 줘야 함
맵 데이터 저장/로드 하기
35. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일의 가로/세로 정보와 각 타일 정보의 출력 모습
맵 데이터 저장/로드 하기
36. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로에 대한 정보의 출력 모습
맵 데이터 저장/로드 하기
37. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
유니티에서 제공하는 경로에 관한 내용
맵 데이터 저장/로드 하기
Application.persistentDataPath
Application.dataPath
Application.streamingAssetsPath
주소와 관련한 내용 참고 주소 :
1. UnityStudy.net
2. 개발자 블로그
38. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
[ MapManager ] 클래스 내에 파일로드 구현을 위한 함수 구현
맵 데이터 저장/로드 하기
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class MapManager : MonoBehaviour
{
......
// (1, 2, 3) 이라는 문자열을 Vector3값으로 변경해 주는 함수
public Vector3 GetVector3FromString(string text)
{
string newText = text.Replace( '(', ' ' ); // '(' 문자를 ‘ ’문자로 변경
newText = newText.Replace( ')', ' ' ); // ')' 문자를 ‘ ’문자로 변경
string[] datas = newText.Split( ',' ); // ',' 문자를 기준으로 값 분리
float x = float.Parse( datas[0] ); // 각각의 숫자를 x, y, z로 변환
float y = float.Parse( datas[1] );
float z = float.Parse( datas[2] );
return new Vector3(x, y, z);
}
}
39. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
[ MapManager ] 클래스 내에 파일로드 구현
맵 데이터 저장/로드 하기
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class MapManager : MonoBehaviour
{
......
public void LoadMapDataFromFile()
{
RemoveAllTiles();
string filePath = "MapData/" + _fileName;
TextAsset asset = (TextAsset)Resources.Load(
filePath, typeof(TextAsset) );
if (asset == null)
{
Debug.Log("Can not open file on Assets/" + filePath + ".txt");
return;
}
//Stream stream = new MemoryStream(asset.bytes);
//TextReader textReader = new StreamReader(stream);
TextReader textReader = new StringReader(asset.text);
// read width
string text = textReader.ReadLine();
string widthText = text.Substring( text.IndexOf(' ') + 1 );
_currentWidth = int.Parse( widthText );
// read height
text = textReader.ReadLine();
string heightText = text.Substring( text.IndexOf(' ') + 1 );
_currentHeight = int.Parse( heightText );
......
}
} // End of LoadMapDataFromFile()
}
40. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
타일의 정보 읽어오는
기능 구현
맵 데이터 저장/로드 하기
public class MapManager : MonoBehaviour
{
......
public void LoadMapDataFromFile()
{
......
// create map
_tiles = new GameObject[_currentWidth, _currentHeight];
for (int i = 0; i < _currentWidth; ++i)
{
for (int j = 0; j < _currentHeight; ++j)
{
text = textReader.ReadLine();
string[] infos = text.Split('t');
GameObject obj = Instantiate(_baseTilePrefab) as GameObject;
obj.name = i + "_" + j;
obj.transform.parent = transform;
obj.transform.localPosition = GetVector3FromString( infos[0] );
obj.transform.eulerAngles = GetVector3FromString( infos[1] );
TileInfo tileInfo = obj.GetComponent<TileInfo>();
tileInfo.currentTileStyle = (TILESTYLE)( int.Parse( infos[2] ) );
tileInfo.UpdateMaterial();
_tiles[i, j] = obj;
}
}
......
} // End of LoadMapDataFromFile()
}
41. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로 정보 읽어오는
기능 구현
맵 데이터 저장/로드 하기
public class MapManager : MonoBehaviour
{
......
public void LoadMapDataFromFile()
{
......
// load path
text = textReader.ReadLine();
string pathCountText = text.Substring(text.IndexOf(‘ '));
int pathCount = int.Parse(pathCountText);
for (int i = 0; i < pathCount; ++i)
{
text = textReader.ReadLine();
string[] tiles = text.Split('t');
int x = int.Parse(tiles[0]);
int y = int.Parse(tiles[1]);
_pathList.Add( _tiles[x, y].transform );
}
} // End of LoadMapDataFromFile()
}
42. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로를 실제 읽어올 수 있도록 함수 호출 구문 추가
맵 데이터 저장/로드 하기
public class MapManagerInspector : Editor
{
void DrawSaveLoadButton( MapManager mapManager )
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Save Map Data"))
{
//Save Process
……
}
if (GUILayout.Button("Load Map Data"))
{
// Load Process
mapManager.LoadMapDataFromFile();
}
EditorGUILayout.EndHorizontal();
}
}
43. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
맵 데이터 저장/로드 하기
void RepairMapTilesProcess(MapManager mapManager)
{
if( mapManager._tiles != null )
return;
int maxX = -1000;
int maxY = -1000;
int count = 0;
foreach( Transform child in mapManager.transform )
{
string name = child.name;
string[] tile = name.Split('_');
int currentX = int.Parse( tile[0] );
int currentY = int.Parse( tile[1] );
maxX = Mathf.Max( currentX, maxX );
maxY = Mathf.Max( currentY, maxY );
++count;
}
++maxX;
++maxY;
if( count != maxX*maxY)
{
EditorUtility.DisplayDialog("Notice", "I can not repair your map. Sorry...",
"OK");
return;
}
mapManager._tiles = new GameObject[maxX, maxY];
foreach( Transform child in mapManager.transform )
{
string name = child.name;
string[] tile = name.Split('_');
int currentX = int.Parse( tile[0] );
int currentY = int.Parse( tile[1] );
mapManager._tiles[currentX, currentY] = child.gameObject;
}
}
44. 본 자료는 유니티 러닝센터 수강생을 위한 수업 교재로, 저작권은 유니티테크놀로지스코리아가 소유하고 있습니다.
경로를 실제 읽어올 수 있도록 함수 호출 구문 추가
맵 데이터 복구하기
public class MapManagerInspector : Editor
{
public override void OnInspectorGUI()
{
MapManager mapManager = target as MapManager;
......
CommonEditorUi.DrawSeparator( Color.cyan );
if( GUILayout.Button("Repair Map Tiles" ) )
{
RepairMapTilesProcess(mapManager);
}
}