전제 ) Editor폴더안에 스크립트가 존재해야한다.
이는 유니티의 예약폴더시스템인데, Resouces폴더와 같은 느낌이다.
2.클래스의 위에 [CustomEditor(typeof('Class이름'))] 즉, 커스텀 에디터를 적용할 클래스
위 단계가 모두 기본 전제에 가깝다고 볼 수 있다.
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(GameManager))]
public class GameManagerEditor : Editor
{
public override void OnInspectorGUI()
{
var manager = target as GameManager;
EditorGUILayout.ObjectField("스크립트", MonoScript.FromMonoBehaviour((MonoBehaviour)manager), typeof(GameManager),
false);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("적 생성"))
{
manager.SpawnEnemy();
}
if (GUILayout.Button("적 제거"))
{
var enemies = GameObject.FindGameObjectsWithTag("Enemy");
foreach (var enemy in enemies)
{
DestroyImmediate(enemy);
}
}
EditorGUILayout.EndHorizontal();
}
}
using UnityEditor;
using UnityEngine;
public class ItemCreator : EditorWindow
{
private string itemName = "New Item";
private ItemType itemType = ItemType.Weapon;
private int quantity = 1;
private bool isMultiple = false;
[MenuItem("Window/Item Creator")]
private static void ShowWindow()
{
GetWindow<ItemCreator>("아이템 생성");
}
private void OnGUI()
{
itemName = EditorGUILayout.TextField("아이템 명",itemName);
itemType = (ItemType)EditorGUILayout.EnumPopup("아이템 종류", itemType);
quantity = EditorGUILayout.IntField("수량", quantity);
isMultiple = EditorGUILayout.Toggle("복수 여부", isMultiple);
if (GUILayout.Button("아이템 생성"))
{
ItemData data = ScriptableObject.CreateInstance<ItemData>();
data.itemName = itemName;
data.itemType = itemType;
data.quantity = quantity;
data.isMultiple = isMultiple;
AssetDatabase.CreateAsset(data, $"Assets/02_Scripts/Items/{itemName}.asset");
AssetDatabase.SaveAssets();
}
}
}
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PlayerStats))]
public class PlayerStatsEditor : Editor
{
public override void OnInspectorGUI()
{
var playerStats = (PlayerStats)target;
EditorGUILayout.Space();
EditorGUILayout.HelpBox("주인공 캐릭터 스텟", MessageType.Info);
EditorGUILayout.Space();
playerStats.hp = EditorGUILayout.IntField("생명", playerStats.hp);
playerStats.mp = EditorGUILayout.IntSlider("Mp", playerStats.mp,0,100);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(playerStats.isGodMode? "일반모드로 전환" : "무적모드로 전환"))
{
playerStats.isGodMode = !playerStats.isGodMode;
}
if (GUILayout.Button("데이터 초기화"))
{
playerStats.InitPlayerData();
}
EditorGUILayout.EndHorizontal();
}
}
예시 2번의 경우 스크립터블 오브젝트를 쉽게 만들 수 있는 커스텀 에디터이기 때문에 잘 기억해놓자.
using System.Collections.Generic;
using System;
public class Solution {
public int[] solution(string[] park, string[] routes)
{
int[]currentPoint = new int[]{0,0};
Dictionary<(int,int),bool> maze = new Dictionary<(int,int),bool>();
for(int i = 0; i < park.Length; i++)
{
for(int j=0; j < park[i].Length; j++)
{
switch(park[i][j])
{
case 'S':
currentPoint = new int[]{i,j};
maze.Add((i,j),true);
break;
case 'O':
maze.Add((i,j),true);
break;
case 'X':
maze.Add((i,j),false);
break;
}
}
}
for(int i = 0; i < routes.Length; i++)
{
string move = routes[i].Replace(" ",string.Empty);
int repeat = int.Parse(move[1].ToString());
int[] totalMove = new int[2];
int[] direction = new int[2];
switch(move[0])
{
case 'S':
totalMove = new []{repeat,0};
direction = new []{1,0};
break;
case 'N':
totalMove = new []{-repeat,0};
direction = new []{-1,0};
break;
case 'E':
totalMove = new []{0,repeat};
direction = new []{0,1};
break;
case 'W':
totalMove = new []{0,-repeat};
direction = new []{0,-1};
break;
}
if(maze.ContainsKey((currentPoint[0]+totalMove[0],currentPoint[1]+totalMove[1])) && maze[(currentPoint[0]+totalMove[0],currentPoint[1]+totalMove[1])])
{
bool isObstacle = false;
int[]tempPoint=new[]{0,0};
for(int k = 1; k < repeat+1; k++)
{
tempPoint =new int[]{currentPoint[0]+direction[0]*k,currentPoint[1]+direction[1]*k};
if(!maze[(tempPoint[0],tempPoint[1])])
{
isObstacle = true;
}
}
if(!isObstacle)
{
currentPoint = tempPoint;
}
}
}
return currentPoint;
}
}
처음에 문제풀이의 방향을 잘못잡은게 가장 큰 문제였다.
Dictionary에 모든 배열의 값을 넣어놓고 하나씩 찾아가게 만드려 했는데, int[]는 참조값이라 동일한 value가 내부에 있어도 동일하다고 판단하지 않는다. 따라서 튜플로 이를 수정하였다.
이차원 배열을 쓸 일이 잘 없어서 자꾸 실수하는 문제점을 추가로 정리하면
이차원 배열에 참조를 할 때, [i][j]형태로 한다.
문자열의 경우 하나의 문자에 접근하게 될 경우 이는 'char'로 간주된다.
추가적으로, 정수형 배열을 생성할 때는
int[] arrInt = new int[]{}; 꼴이다. new int에서 int는 생략이 되긴한다.
나름 많은 걸 배워서 문제는 잘 선정한 것 같다.