맵 제작을 위한 맵 에디터의 기반을 만들어주었습니다.
파란색이 교수측 플레이어 캐릭터의 생성위치, 노란색이 학생측 플레이어의 생성위치를 표기하며, 붉은색은 유령의 생성위치를 표기합니다.
Generate players spawn 버튼으로 2명의 플레이어 스폰 위치를 생성 할 수 있으며, Generate ghost spawn 으로 유령이 스폰될 위치를 정해줄 수 있습니다.
플레이어는 2명으로 고정되어있으며, 현재로써는 스폰 위치가 고정될 예정이기때문에 각각 하나씩의 스폰위치가 생성되면 이후로는 생성되지 않습니다.
유령의 경우 다수의 스폰 위치를 사용할 수 있으며, 이후 모든 위치에서 스폰이 될지, 일부 위치에서만 스폰시킬지 결정하게될듯 합니다.
Set spawn positions as Inspactor 와 Set spawn positions as Hierarchy 버튼의 경우 컴포넌트에 저장된 위치정보와 씬에 올라와있는 위치정보를 동기화 시켜주는 버튼입니다.
as Inspactor 를 누를경우 컴포넌트에 적어준 좌표로 씬에 위치한 오브젝트들의 실제 위치가 변경되며
as Hierarchy 를 누르면 씬의 오브젝트들 좌표로 컴포넌트의 정보가 변경되게 됩니다.
Remove players 와 Remove Ghosts 는 각각 씬의 플레이어 스폰위치, 유령 스폰위치를 전부 삭제시키는 역할을 합니다
Undo Ghost Spawn 의 경우, 마지막에 생성된 유령 스폰위치를 지우는 역할을 합니다.
아래는 에디터 제작에 사용된 코드 내용입니다.
에디터의 전체 내용입니다.
public class MapEditManager : MonoBehaviour
{
public SpawnPointObject spawnPointPrefab;
[Header("Map Setting")]
public int mapNumber = 1;
public string mapSavePath = "Assets/Maps";
[Header("Player Spawn Positions")]
public Vector3 professorPosition;
public Vector3 studentPosition;
private bool isPlayersCreated = false;
private Transform professroTransform;
private Transform studentTransform;
[Header("Ghost Spawn Positions")]
public List<Vector3> ghostPositions = new List<Vector3>();
private List<Transform> ghostTransforms = new List<Transform>();
//스폰포인트용
private Color professorSpawnPointColor = Color.blue;
private Color studentSpawnPointColor = Color.yellow;
private Color ghostSpawnPointColor = Color.red;
//플레이어 스폰 위치 생성
public void CreatePlayerStartPosition()
{
if (isPlayersCreated) return;
SpawnPointObject professor = Instantiate(spawnPointPrefab, new Vector3(0, 0, 0), Quaternion.identity, transform);
professor.OnCreated("Professor Spawn Point", professorSpawnPointColor);
SpawnPointObject student = Instantiate(spawnPointPrefab, new Vector3(5,0,0), Quaternion.identity, transform);
student.OnCreated("Student Spawn Point", studentSpawnPointColor);
professorPosition = professor.transform.position;
studentPosition = student.transform.position;
professroTransform = professor.transform;
studentTransform = student.transform;
isPlayersCreated = true;
}
//인스펙터창 기준으로 위치 변경
public void SetPlayersPositonAsInspector()
{
if(!isPlayersCreated) return;
professroTransform.localPosition = professorPosition;
studentTransform.localPosition = studentPosition;
}
//씬 기준으로 위치 변경
public void SetPlayersPositionAsHierarchy()
{
if (!isPlayersCreated) return;
professorPosition = professroTransform.localPosition;
studentPosition = studentTransform.localPosition;
}
public void ClearPlayers()
{
if (!isPlayersCreated) return;
professorPosition = Vector3.zero;
studentPosition = Vector3.zero;
DestroyImmediate(professroTransform.gameObject);
DestroyImmediate(studentTransform.gameObject);
professroTransform = null;
studentTransform = null;
isPlayersCreated = false;
}
//유령 생성 위치
public void CreateGhostPosition()
{
SpawnPointObject ghost = Instantiate(spawnPointPrefab, new Vector3(0, 0, 0), Quaternion.identity, transform);
ghost.OnCreated("Ghost Spawn Point", ghostSpawnPointColor);
ghostPositions.Add(ghost.transform.position);
ghostTransforms.Add(ghost.transform);
}
public void SetGhostPositionsAsInspector()
{
for(int i = 0; i < ghostPositions.Count; i++)
{
ghostTransforms[i].localPosition = ghostPositions[i];
}
}
public void SetGhostPositionsAsHierarchy()
{
for(int i = 0; i < ghostPositions.Count; i++)
{
ghostPositions[i] = ghostTransforms[i].localPosition;
}
}
public void DestroyLastGhostPosition()
{
if (ghostPositions.Count == 0) return;
int lastIndex = ghostPositions.Count - 1;
ghostPositions.RemoveAt(lastIndex);
Transform ghost = ghostTransforms[lastIndex];
ghostTransforms.RemoveAt(lastIndex);
DestroyImmediate(ghost.gameObject);
}
public void ClearGhostPositions()
{
if (ghostPositions.Count == 0) return;
int count = ghostPositions.Count;
for (int i = 0; i < count; i++)
{
DestroyLastGhostPosition();
}
}
}
Editor 를 상속받는, 커스텀 에디터 클래스입니다
[CustomEditor(typeof(MapEditManager))]
public class MapEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
GUILayout.Space(10);
MapEditManager manager = (MapEditManager)target;
if(GUILayout.Button("Generate players spawn"))
{
manager.CreatePlayerStartPosition();
}
if(GUILayout.Button("Generate ghost spawn"))
{
manager.CreateGhostPosition();
}
GUILayout.Space(10);
if(GUILayout.Button("Set sapwn positions as Inspactor"))
{
manager.SetPlayersPositonAsInspector();
manager.SetGhostPositionsAsInspector();
}
if(GUILayout.Button("Set spawn positions as Hierarchy"))
{
manager.SetPlayersPositionAsHierarchy();
manager.SetGhostPositionsAsHierarchy();
}
GUILayout.Space(10);
if(GUILayout.Button("Remove players"))
{
manager.ClearPlayers();
}
if(GUILayout.Button("Remove Ghosts"))
{
manager.ClearGhostPositions();
}
if(GUILayout.Button("Undo Ghost spawn"))
{
manager.DestroyLastGhostPosition();
}
}
}
이후 만들어준 내용을 전부 json으로 저장하고, 저장된 내용을 기반으로 맵을 생성해줄 예정입니다.
[System.Serializable]
public class MapData
{
//플레이어들 시작 위치
public Vector3 professorSpawnPos;
public Vector3 studentSpawnPos;
//유령, 아이템 생성 위치
public Vector3 ghostSpawnPos;
public List<Vector3> itemSpawnPos;
//퍼즐 정보...TODO
//구조물 관련
public List<string> structureResourcePaths;
public List<Vector3> structurePositions;
}
위 내용에서 구조물에 대한 내용을 아직 어떻게 해야할지 고민중인 상태입니다.
별도 씬에서 구조물을 배치한 후, 해당 내용을 묶은 뒤 프리팹화 시켜서 저장을 시켜줄지,
에디터상에서 맵을 제작할 수 있도록 리소스 파일에 구조물을 프리팹으로 저장한 뒤, 프리팹의 주소와 배치 위치를 저장하여 씬이 시작될 때 리소스에서 똑같이 만들어줄 수 있도록 만들지
또한 이러한 내용을 어떻게 구현해줄것인지 고민중입니다.
제작중 크게 막히는 내용은 없었기 때문에, 트러블슈팅은 없습니다.
'내일배움캠프 > 프로젝트' 카테고리의 다른 글
팀 프로젝트 - 맵 데이터, 맵 생성 (0) | 2024.12.16 |
---|---|
팀 프로젝트 - 아이템 기반 (1) | 2024.12.13 |
팀 프로젝트 - 클라이언트 캐릭터 위치문제 (0) | 2024.12.10 |
팀 프로젝트 - 오브젝트 스폰 시점 수정, 로딩 씬 추가 (0) | 2024.12.09 |
팀 프로젝트 - 리팩토링 대상 정리 (0) | 2024.12.05 |