Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 백준
- 코테
- C#
- c++
- 2870번 수학숙제 c++
- 오브젝트 풀링
- 수학숙제
- 유니티
- 백준 c++ 2468번
- 백준 17070번 c++
- 백준 1103번 게임
- 2870번 c++
- 프로그래머스
- Algorithm
- Lv2
- 백준 2870번
- 코딩테스트
- 2468 c++
- 백준 1103번
- 2870번
- 2870번 수학숙제
- 플레이어 이동
- 백준 c++ 2870번
- Lv.3
- 17070번
- 백준 1103번 c++
- dfs
- Unity
- 백준 17070번
- Beakjoon
Archives
- Today
- Total
주녘공부일지
[해피스케치] 에디터 인스펙터 툴 (카메라, 스테이지) 본문
플레이 영상
해피스케치의 요청에 따라 모션 감지를 이용한 AR게임 프로토타입 모델
- 여러 가지 미니게임 스테이지를 구현하여 2명의 사용자가 대전을 하는 AR 멀티 게임
- PC버전으로 선 구현 후 채택 시 AR 멀티 게임으로 확장
에디터 인스펙터 툴
- 기획자는 프로그래머를 거치지 않고, EditScene에서 각 스테이지를 플레이해보며 카메라 뷰를 변경하여 저장하거나 각 스테이지에서 사용되는 객체에 대한 엑셀 데이터 값을 변경하는 것으로 인게임에 대한 값 조정 및 테스트를 할 수 있게 함
1. 스테이지 에디터
- 인게임에서 사용되는 Stage를 소환하여 테스트해볼 수 있음
- 기획자가 직접 특정 스테이지를 플레이해보며 엑셀 데이터를 변경하여 제이슨으로 파싱하고 인게임에 적용된 데이터로 플레이해볼 수 있음
ex) 몬스터 이동속도, 스턴 시간 등에 대한 데이터 등
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using static Define;
public class StageEditor : InitBase
{
[SerializeField, ReadOnly] CameraEditor cameraEditor;
[SerializeField, ReadOnly] BaseStage currStage = null;
[SerializeField, ReadOnly] Player player = null;
[SerializeField, ReadOnly] Transform playerStartPoint;
[Header("[ 스테이지 세팅 영역 ]")]
[Space(5f)]
public EStageType StageType = EStageType.None;
private void Start()
{
PlayStage();
}
public override bool Init()
{
if (base.Init() == false)
return false;
cameraEditor = FindObjectOfType<CameraEditor>();
currStage = FindObjectOfType<BaseStage>();
StageType = currStage.StageType;
if (currStage == null)
{
Debug.LogError("스테이지를 소환하고 테스트해주세요.");
UnityEditor.EditorApplication.isPlaying = false;
}
return true;
}
public void SpawnStage()
{
currStage = FindObjectOfType<BaseStage>();
if (currStage != null)
{
GameObject.DestroyImmediate(currStage.gameObject);
}
if (StageType == EStageType.None)
{
Debug.LogWarning("소환할 스테이지 타입을 설정해주세요.");
return;
}
string loadPath = $"{Application.dataPath}/Resources/Prefabs/{PrefabPath.STAGE_PATH}/{StageType}.prefab";
GameObject go = PrefabUtility.LoadPrefabContents(loadPath);
Util.Editor_InstantiateObject(go);
}
public void PlayStage()
{
Managers.Game.SetStageId((int)StageType);
Managers.Game.StartStage();
LightingController.SetStageLighting(StageType);
playerStartPoint = Util.FindChild<Transform>(currStage.gameObject, "PlayerStartPoint", true);
player = Managers.Resource.Instantiate($"{PrefabPath.OBJECT_PLAYER_PATH}/LeftPlayer").GetComponent<Player>();
player.transform.position = playerStartPoint.position;
player.transform.position += Vector3.up * player.GetColliderHeight();
player.SetInfo((int)StageType);
cameraEditor.SetTarget(player);
switch(currStage)
{
case MultiStage multiStage:
multiStage.SetInfo(player);
multiStage.ConnectEvents(null);
break;
case SingleStage singleStage:
singleStage.SetInfo(player, player);
singleStage.ConnectEvents(null);
break;
}
currStage.StartStage();
}
}
#endif
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(StageEditor))]
public class EditStage : Editor
{
bool isSpawnStageUnlocked = false;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
StageEditor stageEditor = (StageEditor)target;
GUILayout.Space(10);
GUILayout.Label("[ 스테이지 에디터 ]", EditorStyles.boldLabel);
GUILayout.Space(10);
isSpawnStageUnlocked = EditorGUILayout.Toggle("스테이지 소환 잠금 해제", isSpawnStageUnlocked);
GUILayout.Space(5);
if (GUILayout.Button("스테이지 소환") && isSpawnStageUnlocked)
{
isSpawnStageUnlocked = false;
stageEditor.SpawnStage();
Debug.Log("스테이지 소환 완료");
}
GUILayout.Space(20);
}
}
2. 카메라 에디터
- 인게임에서 사용되는 TeamCamera 클래스를 상속받아 CameraEditor를 구현
- 기획자가 직접 특정 스테이지의 카메라 세팅 값을 설정하여 런타임에 Save&Load 할 수 있음
- 스테이지가 로드되면 저장되어 있던 데이터를 스테이지 시작 시 로드하여 세팅하도록 설계
ex) 몬스터 이동속도, 스턴 시간 등에 대한 데이터 등
#if UNITY_EDITOR
using System;
using System.IO;
using UnityEngine;
public class CameraEditor : TeamCamera
{
[SerializeField, ReadOnly] StageEditor stageEditor;
[Header ("[ 카메라 세팅 영역 ]")]
[Space(5f)] [SerializeField, ReadOnly]
EStageType stageType = EStageType.None;
[Space(5f)] [SerializeField]
BaseObject testTarget;
[Space(10f)]
[Range(0f, 180f)] [SerializeField] float fieldOfView = 60f;
[Range(5f, 20f)] [SerializeField] float targetDistance = 5f;
[Range(-10f, 30f)] [SerializeField] float cameraHeight = 5f;
[Range(-10f, 40f)] [SerializeField] float lookAtHeight = 0f;
[Range(0f, 20f)] [SerializeField] float nearClipping = 0.3f;
[Range(20f, 1000f)] [SerializeField] float farClipping = 1000f;
private void Update()
{
if(testTarget != null)
SetTarget(testTarget);
UpdateCameraInfo();
}
private void Start()
{
stageType = stageEditor.StageType;
}
public override bool Init()
{
if (base.Init() == false)
return false;
stageType = EStageType.None;
cameraInfoData = new CameraInfoData(fieldOfView, targetDistance, cameraHeight, lookAtHeight, nearClipping, farClipping);
stageEditor = FindObjectOfType<StageEditor>();
return true;
}
public override void SetTarget(BaseObject target)
{
base.SetTarget(target);
LoadCameraInfo();
}
public void InitCameraInfo()
{
fieldOfView = 60f;
targetDistance = 5f;
cameraHeight = 5f;
lookAtHeight = 0f;
nearClipping = 0.3f;
farClipping = 1000f;
}
private void UpdateCameraInfo()
{
cameraInfoData.fieldOfView = fieldOfView;
cameraInfoData.targetDistance = targetDistance;
cameraInfoData.cameraHeight = cameraHeight;
cameraInfoData.lookAtHeight = lookAtHeight;
cameraInfoData.nearClipping = nearClipping;
cameraInfoData.farClipping = farClipping;
cam.fieldOfView = cameraInfoData.fieldOfView;
cam.nearClipPlane = cameraInfoData.nearClipping;
cam.farClipPlane = cameraInfoData.farClipping;
}
public bool LoadCameraInfo()
{
if(stageType == EStageType.None)
{
Debug.LogWarning("스테이지 타입을 설정하지 않았습니다.");
return false;
}
bool isLoad = base.LoadCameraDataInfo(stageType);
if(isLoad)
{
fieldOfView = cameraInfoData.fieldOfView;
targetDistance = cameraInfoData.targetDistance;
cameraHeight = cameraInfoData.cameraHeight;
lookAtHeight = cameraInfoData.lookAtHeight;
nearClipping = cameraInfoData.nearClipping;
farClipping = cameraInfoData.farClipping;
}
return isLoad;
}
public bool SaveCameraInfo()
{
if (stageType == EStageType.None)
{
Debug.LogWarning("스테이지 타입을 설정하지 않았습니다.");
return false;
}
string savePath = Application.dataPath + DataPath.STAGE_JSONDATA_PATH + $"/CameraData{(int)stageType}";
Util.Editor_FileDelete(savePath);
string jsonData = JsonUtility.ToJson(cameraInfoData);
File.WriteAllText(savePath + ".json", jsonData);
return true;
}
}
#endif
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(CameraEditor))]
public class EditCamera : Editor
{
bool isInitUnlocked = false;
bool isLoadUnlocked = false;
bool isSaveUnocked = false;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
CameraEditor cameraEditor = (CameraEditor)target;
GUILayout.Space(10);
GUILayout.Label("[ 카메라 에디터 ]", EditorStyles.boldLabel);
// 초기 값 세팅
GUILayout.Space(10);
isInitUnlocked = EditorGUILayout.Toggle("초기 세팅 잠금 해제 ", isInitUnlocked);
GUILayout.Space(5);
if (GUILayout.Button("초기 값으로 세팅") && isInitUnlocked)
{
isInitUnlocked = false;
cameraEditor.InitCameraInfo();
Debug.Log("초기 값으로 세팅 완료");
}
// 데이터 불러오기
GUILayout.Space(5);
isLoadUnlocked = EditorGUILayout.Toggle("불러오기 잠금 해제 ", isLoadUnlocked);
GUILayout.Space(5);
if (GUILayout.Button("데이터 불러오기") && isLoadUnlocked)
{
isLoadUnlocked = false;
if(cameraEditor.LoadCameraInfo())
Debug.Log("스테이지 데이터 불러오기 완료");
}
// 데이터 저장
GUILayout.Space(5);
isSaveUnocked = EditorGUILayout.Toggle("저장하기 잠금 해제 ", isSaveUnocked);
GUILayout.Space(5);
if (GUILayout.Button("데이터 저장하기") && isSaveUnocked)
{
isSaveUnocked = false;
if (!IsPlayEditor())
{
Debug.LogError("오류! : 세이브는 에디터 실행 상태에서 해야합니다.");
return;
}
if (cameraEditor.SaveCameraInfo())
Debug.Log("스테이지 데이터 저장하기 완료");
}
GUILayout.Space(20);
}
private bool IsPlayEditor() => Application.isEditor && Application.isPlaying;
}
'GameDevelopment > [Unity] Project' 카테고리의 다른 글
[더 챌린저스] 오브젝트 풀링 (0) | 2024.12.27 |
---|---|
[해피스케치] 스테이지 관리 및 제어 (0) | 2024.12.10 |
[마법사의 길] 캐릭터, 몬스터 AI 상태 관리 (0) | 2024.09.09 |
[더 챌린저스] 동기화(RPC) & 네트워크(Photon) (1) | 2024.09.09 |
[더 챌린저스] 캐릭터 (0) | 2024.09.09 |