Get it on Google Play


Wm뮤 :: 유니티 에디터 윈도우

블로그 이미지
가끔 그림그리거나 3D모델링하거나
취미로 로봇만드는
퇴직한 전자과 게임프로그래머
2020.3.48f1 , 2022.3.6f1 주로 사용
모카쨩
@Ahzkwid

Recent Comment

Archive


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

 

오브젝트 스왑

더보기

 

ObjectSwapToolWindow v0.0.2.unitypackage
0.00MB
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"));
    }
}

 

 

'Unity > C#' 카테고리의 다른 글

오큘러스 함수들  (0) 2021.05.16
코드 모음 사이트  (0) 2021.01.24
수학 Math  (0) 2021.01.18
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입