2021. 4. 12. 01:14
Unity/C#
prefs에 저장되는 datetime
public static System.DateTime DTime
{
get
{
string time = EditorPrefs.GetString(nameof(DTime), "none");
if (time == "none")
{
DTime = System.DateTime.Now;
return DTime;
}
return System.DateTime.Parse(EditorPrefs.GetString((nameof(DTime)), "none"));
}
set
{
EditorPrefs.SetString(nameof(DTime), value.ToString());
}
}
prefs에 저장되는 Texture2D
public static Texture2D AppIcon
{
get
{
var path = EditorPrefs.GetString(nameof(AppIcon), null);
if (path==null)
{
return null;
}
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
return texture;
}
set
{
EditorPrefs.SetString(nameof(AppIcon), AssetDatabase.GetAssetPath(value));
}
}
오브젝트 복제 툴
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
[InitializeOnLoad]
class OtheloPieceCloningWindow : EditorWindow
{
public GameObject targetGameObject;
public Vector2 cloningMaxCount = new Vector2(8, 8);
public Vector2 interval = new Vector2(0.09f, 0.09f);
[UnityEditor.MenuItem("CustomWindow/" + nameof(OtheloPieceCloningWindow))]
public static void Init()
{
GetWindow<OtheloPieceCloningWindow>(false, nameof(OtheloPieceCloningWindow));
}
SerializedObject serializedObject;
void OnGUI()
{
if (serializedObject == null)
{
serializedObject = new SerializedObject(this);
}
serializedObject.Update();
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(targetGameObject)));
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(cloningMaxCount)));
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(interval)));
}
serializedObject.ApplyModifiedProperties();
if (GUILayout.Button("복제"))
{
Cloning();
}
}
public void Cloning()
{
GameObject[,] cloningObjects= new GameObject[(int)cloningMaxCount.x, (int)cloningMaxCount.y];
cloningObjects[0, 0] = targetGameObject;
for (int x = 0; x < (int)cloningMaxCount.x; x++)
{
for (int y = 0; y < (int)cloningMaxCount.y; y++)
{
if ((x == 0)&&(y == 0))
{
continue;
}
cloningObjects[x, y] = PrefabUtility.InstantiatePrefab(targetGameObject, targetGameObject.transform.parent) as GameObject;
if (cloningObjects[x, y] == null)
{
cloningObjects[x, y] = Instantiate(targetGameObject, targetGameObject.transform.parent);
}
cloningObjects[x, y].transform.position = targetGameObject.transform.position;
cloningObjects[x, y].transform.localPosition += new Vector3(interval.x * x,0, interval.y * y);
cloningObjects[x, y].name = $"{targetGameObject.name} ({x},{y})";
}
}
}
}
#endif
오브젝트 스왑
더보기
using UnityEngine;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
[InitializeOnLoad]
class ObjectSwapToolWindow : EditorWindow
{
public GameObject[] sources = new GameObject[0];
public GameObject[] targets= new GameObject[0];
public bool randomPrefebs = false;
public bool randomRotate = false;
public Vector3 randomRotateMin = new Vector3(-90, -180, -180);
public Vector3 randomRotateMax = new Vector3 (90,180,180);
public bool createBackup = true;
public Vector2 cloningMaxCount = new Vector2(8, 8);
public Vector2 interval = new Vector2(0.09f, 0.09f);
[UnityEditor.MenuItem("Ahzkwid/Tools/" + nameof(ObjectSwapToolWindow))]
public static void Init()
{
GetWindow<ObjectSwapToolWindow>(false, "AhzkwidPrefebSwapTool");
}
SerializedObject serializedObject;
void OnGUI()
{
if (serializedObject == null)
{
serializedObject = new SerializedObject(this);
}
serializedObject.Update();
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(targets)), new GUIContent("Targets"));
if (targets.Length != 0)
{
targets=System.Array.FindAll(targets, x => x != null);
}
if (targets.Length == 0)
{
GUI.enabled = false;
}
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(randomPrefebs)), new GUIContent("Use Random Prefebs"));
if (randomPrefebs)
{
EditorGUI.indentLevel++;
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(sources)), new GUIContent("Prefebs"));
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(createBackup)));
}
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(randomRotate)), new GUIContent("Use Random Rotate"));
if (randomRotate)
{
EditorGUI.indentLevel++;
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(randomRotateMin)));
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(randomRotateMax)));
}
EditorGUI.indentLevel--;
}
}
serializedObject.ApplyModifiedProperties();
if (!randomPrefebs && !randomRotate)
{
GUI.enabled = false;
}
{
if (GUILayout.Button("교체"))
{
Swap();
}
}
GUI.enabled = true;
}
public void Swap()
{
var clones = new List<GameObject>();
foreach (var target in targets)
{
GameObject clone ;
if (randomPrefebs && sources.Length>0)
{
var source = sources[Random.Range(0, sources.Length)] ;
clone = PrefabUtility.InstantiatePrefab(source, target.transform.parent) as GameObject;
if (clone == null)
{
clone = Instantiate(source, target.transform.parent);
}
}
else
{
clone = target;
}
clone.transform.position = target.transform.position;
clone.transform.rotation = target.transform.rotation;
if (randomRotate)
{
clone.transform.Rotate(Random.Range(randomRotateMin.x, randomRotateMax.x), Random.Range(randomRotateMin.y, randomRotateMax.y), Random.Range(randomRotateMin.z, randomRotateMax.z));
}
if (randomPrefebs && sources.Length > 0)
{
if (createBackup)
{
target.SetActive(false);
target.name += " (Backup)";
}
else
{
DestroyImmediate(target);
}
clones.Add(clone);
}
}
if (clones.Count > 0)
{
targets = clones.ToArray();
}
}
}
#endif
objectfield 예시
string objectPath=null;
void OnGUI()
{
SceneAsset oldScene = null;
if (objectPath!=null)
{
oldScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(objectPath);
}
EditorGUI.BeginChangeCheck();
var newScene = EditorGUILayout.ObjectField("scene", oldScene, typeof(SceneAsset), false) as SceneAsset;
if (EditorGUI.EndChangeCheck())
{
objectPath = AssetDatabase.GetAssetPath(newScene);
}
}
prefs결합방식
string objectPath=null;
void OnGUI()
{
string objectPath = EditorPrefs.GetString(nameof(objectPath), null);
SceneAsset oldScene = null;
if (objectPath!=null)
{
oldScene = AssetDatabase.LoadAssetAtPath<SceneAsset>(objectPath);
}
EditorGUI.BeginChangeCheck();
var newScene = EditorGUILayout.ObjectField("scene", oldScene, typeof(SceneAsset), false) as SceneAsset;
if (EditorGUI.EndChangeCheck())
{
EditorPrefs.SetString(nameof(objectPath), AssetDatabase.GetAssetPath(newScene));
}
}
objectfield 심플버전
Object fieldReturn = null;
EditorGUI.BeginChangeCheck();
{
fieldReturn = EditorGUILayout.ObjectField("Icon", Icon, typeof(Texture2D), false);
}
if (EditorGUI.EndChangeCheck())
{
AndroidIcon = (Texture2D)fieldReturn;
}
json타입
public class SaveData
{
public string appIconPath;
public Texture2D AppIcon
{
get
{
if (appIconPath == null)
{
return null;
}
return AssetDatabase.LoadAssetAtPath<Texture2D>(appIconPath);
}
set
{
appIconPath = AssetDatabase.GetAssetPath(value);
}
}
public static string folderPath
{
get
{
return $"{Application.dataPath}/Editor";
}
}
public static string filePath
{
get
{
return $"{folderPath}/{typeof(WordMasterSDKwindow)}{nameof(SaveData)}.json";
}
}
public void Save()
{
if (System.IO.Directory.Exists(folderPath) == false)
{
System.IO.Directory.CreateDirectory(folderPath);
}
System.IO.File.WriteAllText(filePath, JsonUtility.ToJson(this));
}
public static SaveData Load()
{
if (System.IO.File.Exists(filePath))
{
return JsonUtility.FromJson<SaveData>(System.IO.File.ReadAllText(filePath));
}
else
{
return new SaveData();
}
}
}
에디터윈도우 serializedObject , PropertyField 예제
이거 쓰면 prefs 쓸 필요가 없다. 다만 git에는 안 올라간다
public SceneAsset[] sceneAssets;
void OnGUI()
{
var serializedObject = new SerializedObject(this);
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(sceneAssets)), true);
serializedObject.ApplyModifiedProperties();
}
serializedObject, prefs 혼합예제
단순하게 몇개 필드만 쓸거라면 serializedObject , JSON 혼합보다 낫다
public RenderTexture renderTexture;
public Coordinator coordinator;
public Object folder;
SerializedObject serializedObject;
void OnGUI()
{
string GetKey(string fieldname)
{
return $"{GetType().FullName}+{fieldname}";
}
if (serializedObject == null)
{
serializedObject = new SerializedObject(this);
coordinator = FindObjectOfType<Coordinator>();
{
var path = EditorPrefs.GetString(GetKey(nameof(folder)), null);
if (path != null)
{
folder = AssetDatabase.LoadAssetAtPath<Object>(path);
}
}
{
var path = EditorPrefs.GetString($"{GetType().FullName}+{nameof(renderTexture)}", null);
if (path != null)
{
renderTexture = AssetDatabase.LoadAssetAtPath<RenderTexture>(path);
}
}
}
serializedObject.Update();
{
EditorGUI.BeginChangeCheck();
{
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(coordinator)));
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(folder)));
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(renderTexture)));
}
if (EditorGUI.EndChangeCheck())
{
EditorPrefs.SetString(GetKey(nameof(folder)), AssetDatabase.GetAssetPath(folder));
EditorPrefs.SetString(GetKey(nameof(renderTexture)), AssetDatabase.GetAssetPath(renderTexture));
}
}
serializedObject.ApplyModifiedProperties();
}
serializedObject , JSON 혼합예제
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class SampleWindow : EditorWindow
{
public SceneAsset[] sceneAssets;
[System.Serializable]
public class SaveData
{
public string[] sceneAssetPaths;
public static string FolderPath
{
get
{
return $"{Application.dataPath}/Editor";
}
}
public static string FilePath
{
get
{
return $"{FolderPath}/{typeof(SaveData)}.json";
}
}
public void Save()
{
System.IO.File.WriteAllText(FilePath, JsonUtility.ToJson(this));
}
public static SaveData Load()
{
if (System.IO.File.Exists(FilePath))
{
return JsonUtility.FromJson<SaveData>(System.IO.File.ReadAllText(FilePath));
}
else
{
return new SaveData();
}
}
}
public void Save()
{
if(sceneAssets!=null)
{
saveData.sceneAssetPaths = System.Array.ConvertAll(sceneAssets, x => AssetDatabase.GetAssetPath(x));
}
saveData.Save();
}
public void Load()
{
saveData = SaveData.Load();
sceneAssets = System.Array.ConvertAll(saveData.sceneAssetPaths, x => AssetDatabase.LoadAssetAtPath<SceneAsset>(x));
}
public SaveData saveData;
[UnityEditor.MenuItem("Window/SampleWindow")]
public static void Init()
{
GetWindow<SampleWindow>(false, "SampleWindow");
}
void OnGUI()
{
if (saveData == null)
{
Load();
}
EditorGUI.BeginChangeCheck();
{
var serializedObject = new SerializedObject(this);
EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(sceneAssets)));
serializedObject.ApplyModifiedProperties();
}
if (EditorGUI.EndChangeCheck())
{
Save();
}
}
}
#endif
에디터 상에서 임시변수 저장하고 읽기
익스포트는 안됨
bool 변수=EditorPrefs.GetBool("HashKey", bool기본값);//읽기
EditorPrefs.SetBool("HashKey", 변수);//저장
첫생성시가 아니라 첫 업데이트시 호출
이딴걸 왜 쓰냐면 EditorPrefs같은경우는 생성자 호출시에 사용이 안되기 때문
[InitializeOnLoad]
class 클래스명
{
static 클래스명()
{
EditorApplication.update -= firstUpdate;
EditorApplication.update += firstUpdate;
}
public static void firstUpdate()
{
EditorApplication.update -= firstUpdate;
}
}
시작시 창이 뜨게 할지 두는 체크박스
EditorPrefs같은 경우는 클라우드간 공유가 안 됨
v1
더보기
using UnityEditor;
[InitializeOnLoad]
class 클래스명
{
static 클래스명()
{
EditorApplication.update -= firstUpdate;
EditorApplication.update += firstUpdate;
}
public static void firstUpdate()
{
EditorApplication.update -= firstUpdate;
if ((EditorApplication.isPlaying==false)&&(EditorPrefs.GetBool("HashKey", true)))
{
GetWindow<클래스명>(true);
}
}
void OnGUI()
{
GUILayout.BeginArea(new Rect(0,Screen.height- GUI.skin.box.lineHeight- GUI.skin.window.border.top, Screen.width, GUI.skin.box.lineHeight));
{
EditorPrefs.SetBool("HashKey", GUILayout.Toggle(EditorPrefs.GetBool("HashKey", true), "Show at Startup"));
}
GUILayout.EndArea();
}
}
v2
using UnityEngine;
using UnityEditor;
[InitializeOnLoad]
class SampleWindow : EditorWindow
{
static string showHashKey = "ShowSampleWindow";
static SampleWindow()
{
EditorApplication.update -= FirstUpdate;
EditorApplication.update += FirstUpdate;
}
public static void FirstUpdate()
{
EditorApplication.update -= FirstUpdate;
if (EditorApplication.isPlaying)
{
return;
}
if (EditorPrefs.GetBool(showHashKey, true))
{
Init();
}
}
[UnityEditor.MenuItem("CustomWindow/" + nameof(SampleWindow))]
public static void Init()
{
GetWindow<SampleWindow>(utility:false, title:nameof(SampleWindow));
}
void OnGUI()
{
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
EditorPrefs.SetBool(showHashKey, GUILayout.Toggle(EditorPrefs.GetBool(showHashKey, true), "Show at Startup"));
}
GUILayout.EndHorizontal();
}
}
이미지 표시
static string splashImagePath = "Assets/Editor/Thumbnail.png";
void OnGUI()
{
//이미지표시
{
var path = splashImagePath;
var img = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
if (img == null)
{
GUILayout.Label("Image Load Error", EditorStyles.boldLabel);
GUILayout.Label($"Path: {splashImagePath}", EditorStyles.boldLabel);
}
else
{
var hei = Screen.width * ((float)img.height / img.width);
GUI.DrawTexture(new Rect(0, 0, Screen.width, hei), img);
GUILayout.Space(hei);
}
}
}
이미지 표시 2
//이미지표시
{
var img = scriptableObject.img;
var hei= Screen.width * (img.rect.height / img.rect.width);
GUI.DrawTexture(new Rect(0, 0, Screen.width, hei), img.texture);
GUILayout.Space(hei);
}
사이즈 고정
var window= GetWindow<SampleWindow>(utility:true, title:nameof(SampleWindow));
window.minSize = new Vector2(400, 550);
window.maxSize = window.minSize;
window.Show();
에디터 맨 마지막에 표시
v1
더보기
GUILayout.BeginArea(new Rect(0,Screen.height- GUI.skin.box.lineHeight- GUI.skin.window.border.top, Screen.width, GUI.skin.box.lineHeight));
{
}
GUILayout.EndArea();
v2
GUILayout.FlexibleSpace();
GUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
//내용
}
GUILayout.EndHorizontal();
EditorWindow
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
[InitializeOnLoad]
class TooltipWindow : EditorWindow
{
static string ShowToolTip_HashKey = "TooltipWindow_ShowToolTip";
static bool ShowToolTip_DefaultValue = true;
static TooltipWindowScriptableObject tooltipWindowScriptableObject;
static TooltipWindow()
{
EditorApplication.update -= firstDraw;
EditorApplication.update += firstDraw;
}
public static void firstDraw()
{
EditorApplication.update -= firstDraw;
if ((EditorApplication.isPlaying==false)&&(EditorPrefs.GetBool(ShowToolTip_HashKey, ShowToolTip_DefaultValue)))
{
Init();
}
}
[UnityEditor.MenuItem("CustomWindow/Control Panel")]
public static void Init()
{
GetWindow<TooltipWindow>(false,"윈도우 이름");
}
void OnGUI()
{
csvScriptableObject = AssetDatabase.LoadAssetAtPath<TooltipWindowScriptableObject>($"Assets/TooltipWindowScriptableObject.asset");
EditorPrefs.SetBool(ShowToolTip_HashKey, GUILayout.Toggle(EditorPrefs.GetBool(ShowToolTip_HashKey, ShowToolTip_DefaultValue), "Show at Startup"));
}
}