Get it on Google Play


Wm뮤 :: 'Unity' 카테고리의 글 목록 (22 Page)

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

Recent Comment

Archive


2020. 5. 19. 21:48 Unity/C#

//손이 많이가지만 많은 기능을 쓸수 있습니다.

 

 

 

 

기본형

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(RoomGoto))]
public class RoomGoto_Inspector : Editor
{
    public override void OnInspectorGUI()
    {
        EditorGUILayout.LabelField("버튼조작을 위한 컴포넌트");
    }
}
#endif

public class RoomGoto : MonoBehaviour
{
    public void room_goto(string room_name)
    {
        SceneManager.LoadScene(room_name);
    }
    public void game_quit()
    {
        Application.Quit();
    }
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

기존 인스펙터 호출

public override void OnInspectorGUI()
{
    DrawDefaultInspector();
}

혹은

public override void OnInspectorGUI()
{
    base.OnInspectorGUI();
}

 

 

 

 

버튼 조작시

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();//기본 인스펙터를 받아올때
        serializedObject.Update();
        {
            if (GUILayout.Button("실행"))
            {
                ((SampleClass)target).PressInspecterButton();
            }
            EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.notice)), GUIContent.none);

        }
        serializedObject.ApplyModifiedProperties();


    }
}

#endif
public class SampleClass : MonoBehaviour
{
    [HideInInspector]
    [Header("주석")]
    public string notice;
    
    
    public void PressInspecterButton()
    {
        //버튼을 누를시 활성화될 코드
        if (Application.isPlaying)
        {
            //게임중일때 실행될 코드
        }
        else
        {
            //인스펙터에서 수정중일때 실행될 코드
        }
    }
}

 

 

슬라이더 조작시

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();//기본 인스펙터를 받아올때
        serializedObject.Update();
        {
        
            EditorGUI.BeginChangeCheck();
            {
            	EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.border)));
            }
            if (EditorGUI.EndChangeCheck())
            {
                ((AccountSelect)target).SelectInspecterSlider();
            }
            EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.border)), GUIContent.none);
        }
        serializedObject.ApplyModifiedProperties();


    }
}

#endif
public class SampleClass : MonoBehaviour
{
    [HideInInspector]
    [Header("주석")]
    public string notice;
    
    
    [HideInInspector]
    [Range(0,6)]
    public float border;
    
    public void SelectInspecterSlider()
    {
    	//값변경시 활성화될 코드
    	if (Application.isPlaying)
        {
        	게임중일때 실행될 코드
        }
        else
        {
        	인스펙터에서 수정중일때 실행될 코드
        }
    }
}

 

 

라벨필드

public override void OnInspectorGUI()
{
    EditorGUILayout.LabelField("일반라벨");
    EditorGUILayout.LabelField("굵은글씨", EditorStyles.boldLabel);
}

 

 

 

 

 

메뉴를 만들어야 할때

#if UNITY_EDITOR
using UnityEditor;

public class CustomMenuEditor : Editor
{
    [MenuItem("MyMenu/Run")]
    static void Run()
    {
        //실행되는 코드
    }
}

#endif

 

 

 

 

 

커스텀 윈도우 프로퍼티 필드(수동 serializedObject)

public Object folder;
SerializedObject serializedObject;
void OnGUI()
{
    if (serializedObject == null)
    {
        serializedObject = new SerializedObject(this);
    }
    serializedObject.Update();
    {
        EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(folder)));
    }
    serializedObject.ApplyModifiedProperties();
}

 

 

 

 

비활성필드

GUI.enabled = false;
{
    EditorGUILayout.TextField("Name", "value");
}
GUI.enabled = true;

 

NonSerialized 및 정적필드뷰어

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public void DrawHiddenInspectors()
    {
        serializedObject.Update();
        {
            var fields = target.GetType().GetFields();
            GUI.enabled = false;
            {
                foreach (var field in fields)
                {
                    if ((field.IsStatic) || (field.IsNotSerialized))
                    {

                        var fieldName = field.Name;
                        if (field.IsStatic)
                        {
                            fieldName += " (static)";
                        }
                        var fieldType = field.FieldType;
                        if ((fieldType.IsArray) || ((fieldType.IsGenericType) && fieldType.GetGenericTypeDefinition() == typeof(List<>)))
                        {

                            EditorGUI.indentLevel--;
                            {
                                EditorGUILayout.LabelField($"▼{field.Name}");
                            }
                            EditorGUI.indentLevel++;
                            EditorGUI.indentLevel++;
                            {
                                var arrDatas = (System.Collections.IList)field.GetValue(target);
                                if (arrDatas == null)
                                {
                                    EditorGUILayout.LabelField("null");
                                }
                                else
                                {
                                    EditorGUILayout.TextField($"Size", arrDatas.Count.ToString());
                                    for (int i = 0; i < arrDatas.Count; i++)
                                    {
                                        EditorGUILayout.TextField($"Element {i}", arrDatas[i].ToString());
                                    }
                                }
                            }
                            EditorGUI.indentLevel--;

                        }
                        else if (fieldType.IsClass && (fieldType.IsArray == false) && (fieldType.Equals(typeof(string)) == false))
                        {
                            EditorGUI.indentLevel--;
                            {
                                EditorGUILayout.LabelField($"▼{field.Name}");
                            }
                            EditorGUI.indentLevel++;
                            EditorGUI.indentLevel++;
                            {
                                var fieldValue = field.GetValue(target);
                                var subFields = fieldType.GetFields();
                                foreach (var subField in subFields)
                                {
                                    //subField.GetValue(fieldValue).ToString()
                                    EditorGUILayout.LabelField(subField.Name);
                                }
                            }
                            EditorGUI.indentLevel--;
                        }
                        else
                        {
                            EditorGUILayout.TextField($"{field.Name}", field.GetValue(target).ToString());
                        }
                    }
                }
            }
            GUI.enabled = true;
        }
        serializedObject.ApplyModifiedProperties();
    }
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        DrawHiddenInspectors();

    }
}

#endif
public class SampleClass : MonoBehaviour
{
    public int number = 1;
    public int[] array = new int[] { 1, 2, 3 };
    public static float realStatic = 1.5f;
    public static int numberStatic = 2;
    public static int[] arrayStatic = new int[] { 1,2,3 };



    public static QuestionSelect questionSelect;
    [System.Serializable]
    public class QuestionSelect
    {
        public int number = 1;
        public float real = 2f;
    }
}

 

 

커스텀 readonly

더보기
#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public void BaseInspectorGUI(params string[] readOnlyPropertyNames)
    {
        serializedObject.Update();
        {
            var fields = target.GetType().GetFields();
            foreach (var field in fields)
            {
                if ((field.IsStatic) || (field.IsNotSerialized))
                {
                }
                else
                {
                    if (System.Array.FindIndex(readOnlyPropertyNames, x => x == field.Name) >= 0)
                    {
                        GUI.enabled = false;
                    }
                    EditorGUILayout.PropertyField(serializedObject.FindProperty(field.Name));
                    GUI.enabled = true;
                }
            }
        }
        serializedObject.ApplyModifiedProperties();
    }
    public override void OnInspectorGUI()
    {
        BaseInspectorGUI(nameof(SampleClass.SampleVariable));
    }
}
#endif

 

커스텀 readonly V2

더보기
#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public void BaseOnInspectorGUI(params string[] readOnlyPropertyNames)
    {
        DrawPropertiesExcluding(serializedObject, readOnlyPropertyNames);
        serializedObject.Update();
        {
            GUI.enabled = false;
            foreach (var readOnlyPropertyName in readOnlyPropertyNames)
            {
                EditorGUILayout.PropertyField(serializedObject.FindProperty(readOnlyPropertyName));
            }
            GUI.enabled = true;
        }
    }
    public override void OnInspectorGUI()
    {
        BaseOnInspectorGUI(nameof(SampleClass.SampleVariable));
    }
}
#endif

 

 

 

 

 

 

 

커스텀 히든(v3)

이걸써야 디버그모드에서도 보인다

v2에 비해서 코드는 길어졌지만 script를 숨겨놓게 했다 (m_Script가 표시숨김)

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public override void OnInspectorGUI()
    {
        GUI.enabled = false;
        {
            var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
            EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
        }
        GUI.enabled = true;
        
        serializedObject.Update();
        {
        	DrawPropertiesExcluding(serializedObject, "m_Script",nameof(SampleClass.SampleVariable));
        }
        serializedObject.ApplyModifiedProperties();
    }
}
#endif
더보기

커스텀 히든(v1)

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public void BaseInspectorGUI(params string[] hiddenPropertyNames)
    {
        serializedObject.Update();
        {
            var fields = target.GetType().GetFields();
            foreach (var field in fields)
            {
                if ((field.IsStatic) || (field.IsNotSerialized))
                {
                }
                else
                {
                    if ((System.Array.FindIndex(hiddenPropertyNames, x => x == field.Name) >= 0)==false)
                    {
                        EditorGUILayout.PropertyField(serializedObject.FindProperty(field.Name));
                    }
                }
            }
        }
        serializedObject.ApplyModifiedProperties();
    }
    public override void OnInspectorGUI()
    {
        BaseInspectorGUI(nameof(SampleClass.SampleVariable));
    }
}
#endif

 

 

커스텀 히든(v2)

이걸써야 디버그모드에서도 보인다

[HideInInspector]는 여전히 안보임

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        {
        	DrawPropertiesExcluding(serializedObject,nameof(SampleClass.SampleVariable));
        }
        serializedObject.ApplyModifiedProperties();
    }
}
#endif

 

 

 

값변경 미리보기

미리보기수준에서 끝나는게 아니라 실제로 적용하려면 더티플래그를 박아라

#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        serializedObject.Update();
        {
            EditorGUI.BeginChangeCheck();
            {
                EditorGUILayout.PropertyField(serializedObject.FindProperty(nameof(SampleClass.SampleValue)));
            }
            if (EditorGUI.EndChangeCheck())
            {
                //변경되었을때 실행
            }
            else
            {
                //인스펙터를 벗어났을때 실행
            }

        }
        serializedObject.ApplyModifiedProperties();
    }
}
#endif

 

 

더티플래그를 이용한 프리팹상 저장



if (GUILayout.Button("Auto Setting"))
{
    AutoFind();
    EditorUtility.SetDirty(target); //이부분
}

 

 

 

 

 

 

ReorderableList 예제

튜토리얼 모드에서는 라이프 미표시하는 ReorderableList 예제

더보기

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{

    Hashtable reorderableListTable = new Hashtable();
    public void DrawStageDatas(string propertyPath)
    {

        var reorderableListProperty = serializedObject.FindProperty(propertyPath);

        if (reorderableListTable[propertyPath] == null)
        {
            reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
        }
        var reorderableList = (ReorderableList)reorderableListTable[propertyPath];

        serializedObject.Update();
        {

            //헤더명
            reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");


            //요소

            var elementName = nameof(SampleClass.StageData.stageName);
            reorderableList.drawElementCallback =
            (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                EditorGUI.PropertyField(rect, reorderableListProperty.GetArrayElementAtIndex(index).FindPropertyRelative(elementName));
            };
            reorderableList.DoLayoutList();


            //선택된 필드
            if (reorderableList.index >= 0)
            {
                var index = reorderableList.index;
                if ((reorderableListProperty != null) && (reorderableListProperty.arraySize > 0) && (index < reorderableListProperty.arraySize))
                {
                    var elementAtIndex = reorderableListProperty.GetArrayElementAtIndex(index);

                    if (elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)).boolValue)
                    {
                        //튜토리얼 모드라면 이름과 제한시간만 표시
                        EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)));
                        EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(nameof(SampleClass.StageData.timeLimit)));
                    }
                    else
                    {
                        //기본표시
                        foreach (var field in typeof(SampleClass.StageData).GetFields())
                        {
                            if ((field.IsStatic) || (field.IsNotSerialized))
                            {
                            }
                            else
                            {
                                if (field.Name != elementName)
                                {
                                    EditorGUILayout.PropertyField(elementAtIndex.FindPropertyRelative(field.Name));
                                }
                            }
                        }
                        
                        
                        
                        //life값은 0으로 초기화
                        {
                            var sampleClass = (SampleClass)target;
                            var field = sampleClass.GetType().GetField(propertyPath);
                            var datas = (SampleClass.StageData)field.GetValue(sampleClass);
                            datas[index].life = 0;
                            //구조체라면 field.SetValue(sampleClass, datas)를 사용한다
                        }
                    }
                }
            }

        }
        serializedObject.ApplyModifiedProperties();
    }





    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        DrawStageDatas(nameof(SampleClass.stageDatas));
        DrawStageDatas(nameof(SampleClass.stageDatas2));

    }
}
#endif
public class SampleClass : MonoBehaviour
{

    [HideInInspector]
    public StageData[] stageDatas;
    
    [HideInInspector]
    public StageData[] stageDatas2;

    [System.Serializable]
    public class StageData
    {
        public string stageName;
        public bool isTutorial;
        public int timeLimit;
        public int life;
    }


    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

 

 

 

한칸에 여러줄표시하는 ReorderableList 예제

더보기
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR

using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{

    Hashtable reorderableListTable = new Hashtable();
    public void DrawStageDatas(string propertyPath)
    {

        var reorderableListProperty = serializedObject.FindProperty(propertyPath);

        if (reorderableListTable[propertyPath] == null)
        {
            reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
        }
        var reorderableList = (ReorderableList)reorderableListTable[propertyPath];

        serializedObject.Update();
        {

            //헤더명
            reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");

            //요소크기
            reorderableList.elementHeight = EditorGUIUtility.singleLineHeight * 4;
            
            reorderableList.drawElementCallback =
            (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                var elementProperty = reorderableListProperty.GetArrayElementAtIndex(index);

                var fieldRect = rect;
                fieldRect.height = EditorGUIUtility.singleLineHeight;
                EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.stageName)));
                fieldRect.y += EditorGUIUtility.singleLineHeight;
                EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.isTutorial)));
                fieldRect.y += EditorGUIUtility.singleLineHeight;
                EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.timeLimit)));
                fieldRect.y += EditorGUIUtility.singleLineHeight;
                EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(nameof(SampleClass.StageData.life)));
            };
            reorderableList.DoLayoutList();



        }
        serializedObject.ApplyModifiedProperties();
    }





    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        DrawStageDatas(nameof(SampleClass.stageDatas));
        DrawStageDatas(nameof(SampleClass.stageDatas2));

    }
}
#endif
public class SampleClass : MonoBehaviour
{

    [HideInInspector]
    public StageData[] stageDatas;

    [HideInInspector]
    public StageData[] stageDatas2;

    [System.Serializable]
    public class StageData
    {
        public string stageName;
        public bool isTutorial;
        public int timeLimit;
        public int life;
    }


    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

참고용 단순 예제

 

 

 

 

#if UNITY_EDITOR

using UnityEditor;
using UnityEditorInternal;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{

    Hashtable reorderableListTable = new Hashtable();
    public static System.Type GetType(SerializedProperty property)
    {
        var parentType = property.serializedObject.targetObject.GetType();
        var fieldInfo = parentType.GetField(property.propertyPath);
        return fieldInfo.FieldType;
    }
    public void DrawReorderableList(string propertyPath)
    {

        var reorderableListProperty = serializedObject.FindProperty(propertyPath);

        if (reorderableListTable[propertyPath] == null)
        {
            reorderableListTable[propertyPath] = new ReorderableList(serializedObject, reorderableListProperty);
        }
        var reorderableList = (ReorderableList)reorderableListTable[propertyPath];

        serializedObject.Update();
        {

            //헤더명
            reorderableList.drawHeaderCallback = (rect) => EditorGUI.LabelField(rect, $"{propertyPath} ({reorderableListProperty.arraySize})");


            //요소
            var targetType = GetType(reorderableListProperty).GetElementType();

            reorderableList.elementHeight = EditorGUIUtility.singleLineHeight * Mathf.Max(1, targetType.GetFields().Length);

            reorderableList.drawElementCallback =
            (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                var elementProperty = reorderableListProperty.GetArrayElementAtIndex(index);

                var fieldRect = rect;
                fieldRect.height = EditorGUIUtility.singleLineHeight;


                fieldRect.y -= EditorGUIUtility.singleLineHeight;
                foreach (var fields in targetType.GetFields())
                {
                    fieldRect.y += EditorGUIUtility.singleLineHeight;
                    EditorGUI.PropertyField(fieldRect, elementProperty.FindPropertyRelative(fields.Name));
                }

            };
            reorderableList.DoLayoutList();



        }
        serializedObject.ApplyModifiedProperties();
    }





    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        DrawReorderableList(nameof(SampleClass.stageDatas));
        DrawReorderableList(nameof(SampleClass.stageDatas2));

    }
}
#endif


public class SampleClass : MonoBehaviour
{

    [HideInInspector]
    public StageData[] stageDatas;

    [HideInInspector]
    public StageData[] stageDatas2;

    [System.Serializable]
    public class StageData
    {
        public string stageName;
        public bool isTutorial;
        public int timeLimit;
        public int life;
    }


    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

 

자동화 버전

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

배열길이 임의로 조정

var property=serializedObject.FindProperty(nameof(SampleClass.folders));
if(property.arraySize > 3)
{
    property.arraySize = 3;
}

 

다중배열 표시

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


#if UNITY_EDITOR
//Production Date 2022-10-10 from Ahzkwid
using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassInspecter : Editor
{
    public void Draw2DArray(string targetFieldName)
    {
        bool IsArrayCustom(System.Type type)
        {
            return (type.IsArray) || ((type.IsGenericType) && type.GetGenericTypeDefinition() == typeof(List<>));
        }
        void DrawElement(string label,object ilistObject)
        {
            var ilist = (System.Collections.IList)ilistObject;
            EditorGUI.indentLevel--;
            {
                EditorGUILayout.LabelField(label);
            }
            EditorGUI.indentLevel++;
            EditorGUI.indentLevel++;
            {
                if (ilist == null)
                {
                    EditorGUILayout.LabelField("null");
                }
                else
                {
                    EditorGUILayout.TextField($"Size", ilist.Count.ToString());
                    for (int i = 0; i < ilist.Count; i++)
                    {
                        if (ilist[i] == null)
                        {
                            EditorGUI.indentLevel++;
                            EditorGUILayout.LabelField("null");
                            EditorGUI.indentLevel--;
                            continue;
                        }
                        var elementType = ilist[i].GetType();
                        if (IsArrayCustom(elementType))
                        {
                            DrawElement($"▼Element {i}", ilist[i]);
                        }
                        else
                        {
                            EditorGUILayout.TextField($"Element {i}", ilist[i].ToString());
                        }
                    }
                }
            }
            EditorGUI.indentLevel--;
        }
        serializedObject.Update();
        {
            var fields = target.GetType().GetFields();
            GUI.enabled = false;
            {
                foreach (var field in fields)
                {
                    var fieldName = field.Name;
                    if (fieldName != targetFieldName)
                    {
                        continue;
                    }
                    if (field.IsStatic)
                    {
                        fieldName += " (static)";
                    }
                    var fieldType = field.FieldType;
                    if (IsArrayCustom(fieldType))
                    {
                        DrawElement($"▼{field.Name}", field.GetValue(target));
                    }
                }
            }
            GUI.enabled = true;
        }
        serializedObject.ApplyModifiedProperties();
    }
    public override void OnInspectorGUI()
    {

        base.OnInspectorGUI();
        Draw2DArray(nameof(SampleClass.sampleArray2));
        Draw2DArray(nameof(SampleClass.sampleArray3));
        Draw2DArray(nameof(SampleClass.sampleArray4));
    }
}
#endif

public class SampleClass : MonoBehaviour
{
    public string[] sampleArray;
    public string[][] sampleArray2;
    public string[][] sampleArray3 = new string[1][];
    public string[][][] sampleArray4 = new string[2][][] { new string[1][], new string[1][] };
    // Start is called before the first frame update
    void Start()
    {
        sampleArray2 = new string[8][];
        for (int i = 0; i < sampleArray.Length; i++)
        {
            sampleArray2[i] = new string[8];
        }



        sampleArray3 = new string[2][];
        for (int i = 0; i < sampleArray3.Length; i++)
        {
            sampleArray3[i] = new string[3];
            for (int j = 0; j < sampleArray3[i].Length; j++)
            {
                sampleArray3[i][j] = $"text[{i}][{j}]";
            }
        }


        sampleArray4 = new string[2][][];
        for (int i = 0; i < sampleArray4.Length; i++)
        {
            sampleArray4[i] = new string[2][];
            for (int j = 0; j < sampleArray4[i].Length; j++)
            {
                sampleArray4[i][j] = new string[2];
                for (int k = 0; k < sampleArray4[i][j].Length; k++)
                {
                    sampleArray4[i][j][k] = $"text[{i}][{j}][{k}]";
                }
            }
        }


    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

 

 

오른쪽으로 한칸 들여쓰기

EditorGUI.indentLevel++;
{
    //들어갈 내용
}
EditorGUI.indentLevel--;

 

 

박스 레이아웃 두르기

GUILayout.Space(50);
EditorGUILayout.LabelField("제목", EditorStyles.boldLabel);
GUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUI.indentLevel++;
{
    //들어갈 내용
}
EditorGUI.indentLevel--;
GUILayout.Space(20);
GUILayout.EndVertical();

 

 

 

 

 

자기 자신 스크립트를 표시

GUI.enabled = false;
{
    var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
    EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
}
GUI.enabled = true;

 

 

SerializedProperty To Type

    public static System.Type GetType(SerializedProperty property)
    {
        var parentType = property.serializedObject.targetObject.GetType();
        var fieldInfo = parentType.GetField(property.propertyPath);
        return fieldInfo.FieldType;
    }

 

 

 

 

커스텀 드롭다운

하기는 레이어 드롭다운 예제이다.

var sampleClass = (SampleClass)target;

GUILayout.BeginHorizontal();
{
    GUILayout.Label("Layer");

    int layer = sampleClass.gameObject.layer;
    if (EditorGUILayout.DropdownButton(new GUIContent( LayerMask.LayerToName(layer)), FocusType.Passive))
    {
        GenericMenu menu = new GenericMenu();
        for (int i = 0; i < 32; i++)
        {
            var layerName = LayerMask.LayerToName(i);
            if (string.IsNullOrWhiteSpace(layerName))
            {
                continue;
            }
            menu.AddItem(new GUIContent($"{i}: {layerName}"), false, Callback, i);
        }
        menu.ShowAsContext();


        void Callback(object obj)
        {
            sampleClass.gameObject.layer = (int)obj;
        }
    }
}
GUILayout.EndHorizontal();

 

레이어마스크 드롭다운 예제

근데 내장변수 LayerMask 쓰면 된다 (뻘짓함)

인줄 알았는데 Unsupported type BitField버그때문에 다시 씀

더보기
#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(Crosshair))]
public class CrosshairEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();


        var targetClass = (Crosshair)target;

        serializedObject.Update();
        {
            GUILayout.BeginHorizontal();
            {
                GUILayout.Label("Layer Mask");

                var layerMask = targetClass.layerMask;

                var layerNames = new List<string>();
                for (int i = 0; i < 32; i++)
                {
                    if ((layerMask & (1<<i))==0) //해당 레이어마스크가 미체크면 스킵
                    {
                        continue;
                    }
                    var layerName = LayerMask.LayerToName(i);
                    if (string.IsNullOrWhiteSpace(layerName))
                    {
                        layerName = i.ToString();
                    }
                    layerNames.Add(layerName);
                }
                var name = "";
                switch (layerMask)
                {
                    case 0: //Nothing
                        name = "Nothing";
                        break;
                    case -1: //Everything (-1,~0)
                        name = "Everything";
                        break;
                    default:
                        if (layerNames.Count>3)
                        {
                            name = "Mixed...";
                        }
                        else
                        {
                            name = string.Join(", ", layerNames);
                        }
                        break;
                }
                if (EditorGUILayout.DropdownButton(new GUIContent(name), FocusType.Passive))
                {
                    var menu = new GenericMenu();

                    menu.AddItem(new GUIContent($"Nothing"), layerMask == 0, Callback, 0); //Nothing
                    menu.AddItem(new GUIContent($"Everything"), layerMask == -1, Callback, -1); //Everything
                    for (int i = 0; i < 32; i++)
                    {
                        var layerName = LayerMask.LayerToName(i);

                        var on = (layerMask & (1 << i)) != 0;
                        if (string.IsNullOrWhiteSpace(layerName))
                        {
                            continue;
                        }
                        menu.AddItem(new GUIContent($"{i}: {layerName}"), on, Callback, 1 << i);
                    }
                    menu.ShowAsContext();


                    void Callback(object obj)
                    {
                        switch ((int)obj)
                        {
                            case 0: //Nothing
                            case -1: //Everything (-1,~0)
                                targetClass.layerMask = (int)obj;
                                break;
                            default:
                                targetClass.layerMask ^= (int)obj;
                                break;
                        }
                    }
                }
            }
            GUILayout.EndHorizontal();

        }
        serializedObject.ApplyModifiedProperties();
    }
}
#endif

 

 

 

 

enum to dropdown 예제

아주 가끔 쓰인다

#if UNITY_EDITOR

    using UnityEditor;
    [CustomEditor(typeof(PickupSystem))]
    public class PickupSystemInspecter : Editor
    {
        public enum Piece
        {
            None, Pawn, Knight, Bishop, Rook, Queen, King
        }
        public override void OnInspectorGUI()
        {
            GUI.enabled = false;
            {
                var script = MonoScript.FromMonoBehaviour((MonoBehaviour)target);
                EditorGUILayout.ObjectField("Script", script, typeof(MonoScript), false);
            }
            GUI.enabled = true;


            serializedObject.Update();
            {
                DrawPropertiesExcluding(serializedObject, "m_Script", nameof(PickupSystem.piece));

                GUILayout.BeginHorizontal();
                {
                    GUILayout.Label(nameof(PickupSystem.piece));
                    var pickupSystem = target as PickupSystem;
                    var names = System.Enum.GetNames(typeof(Piece));
                    if (EditorGUILayout.DropdownButton(new GUIContent(names[pickupSystem.piece]), FocusType.Passive))
                    {
                        var menu = new GenericMenu();
                        for (int i = 0; i < names.Length; i++)
                        {
                            if (string.IsNullOrWhiteSpace(names[i]))
                            {
                                continue;
                            }
                            menu.AddItem(new GUIContent($"{i}: {names[i]}"), false, Callback, i);
                        }
                        menu.ShowAsContext();


                        void Callback(object obj)
                        {
                            pickupSystem.piece = (int)obj;
                        }
                    }
                }
                GUILayout.EndHorizontal();


            }
            serializedObject.ApplyModifiedProperties();
        }
    }
#endif

 

 

 

 

 

 

텍스처 표시

        {
            var preview = AssetPreview.GetAssetPreview(loadComputeShader.renderTexture);
            GUILayout.Label(preview);
            EditorGUILayout.LabelField(nameof(LoadComputeShader.renderTexture));
        }

 

 

 

MinMax슬라이더

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


#if UNITY_EDITOR

using UnityEditor;
[CustomEditor(typeof(SampleClass))]
public class SampleClassEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();//기본 인스펙터
        serializedObject.Update();
        {
            var sampleClass = (SampleClass)target;
            var minLimit = sampleClass.minLimit;
            var maxLimit = sampleClass.maxLimit;
            EditorGUILayout.LabelField($"MinMaxSlider ({minLimit},{sampleClass.minVal},{sampleClass.maxVal},{maxLimit})");
            EditorGUILayout.MinMaxSlider(ref sampleClass.minVal, ref sampleClass.maxVal, minLimit, maxLimit);
        }
        serializedObject.ApplyModifiedProperties();


    }
}

#endif


public class SampleClass : MonoBehaviour
{
    public float minVal = -10;
    public float minLimit = -20;
    public float maxVal = 10;
    public float maxLimit = 20;
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

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

SQLite 유니티 사용방법  (0) 2020.05.24
유니티 어트리뷰트  (0) 2020.05.19
UGui 관련  (0) 2020.05.19
posted by 모카쨩
2020. 5. 19. 21:45 Unity/C#

 

인스펙터계열 어트리뷰트

//해당 변수가 어떤 역할인지 위에 굵은 글씨로 표시해줌
[Header("헤더이름")] 

//슬라이더로 표시해줌
[Range(0.5f,1.5f)] 


//슬라이더바가 있는 멀티라인
[TextArea(1,30)]
public string csvData;


//슬라이더바가 없는 고정된 멀티라인
[Mutiline]
public string text;

 

 

변수계열 어트리뷰트

//인스펙터의 변수1에 할당되어있던걸 변수2로 할당함
[UnityEngine.Serialization.FormerlySerializedAs("변수1")]
public int 변수2;

 

 

 

 

 

클래스계열 어트리뷰트

//해당 클래스의 인스펙터를 여러개 동시에 수정가능하도록 함
[CanEditMultipleObjects]


//항상 작동함
[ExecuteAlways]

//해당 클래스가 에디터상태에서도 동작함
[ExecuteInEditMode]

//에디터가 시작될때 호출됨
[UnityEditor.InitializeOnLoad]

//에디터가 시작될때 해당 메소드가 호출됨 static 메소드만 가능
[UnityEditor.InitializeOnLoadMethod]


//특정 컴포넌트를 강제로 추가시킴,클래스 위에 삽입함
[RequireComponent(typeof(Rigidbody))]

//없어질 함수라고 선언함, 클래스계열에도 사용가능하다
[System.Obsolete("미사용되는 함수입니다")]

//동일한 컴포넌트는 2개이상 적용 불가
[DisallowMultipleComponent]

 

 

함수계열 어트리뷰트

//이건 좀 특이하니 하단 참고
[ContextMenu("버튼명")]

 

 

 

 

 

-ContextMenu

public int motionCount;
#if UNITY_EDITOR
    [ContextMenu("함수명")]
    public void UpdateMotionCount()
    {
        motionCount = GetNumberMotionsInBlendTree(GetAnimator(),0,"Blend Tree");
    }
#endif

인스펙터의 컴포넌트 상단에 대고 우클릭하면 함수를 실행할수있는 메뉴가 나옴
프로퍼티 드로워 버튼 찾지 말고 이거 쓰자

 

 

 

 

 

 

 

 

 

미분류

//인스펙터에서 숨기고 지정된 값도 지움, 그리고 디버그모드에서는 보임
//json등에서 public인데 저장안되게 할때도 사용
[System.NonSerialized] 

//인스펙터에서 숨기고 지정된 값은 지우지 않음, 디버그모드에서도 안보임
[HideInInspector] 

//원래는 보이지 않아야할 클래스나 구조체등을 보이게 함
//클래스나 구조체형을 인스펙터에 표시할때 사용
[System.Serializable]

//private 필드를 보이게 함
//인스펙터에서 수정은 가능한데 스크립트로는 못하게 하는것
[SerializeField]

//선언된 Define이 있을때만 작동, #if와 조금 다른점은 define이 없을때 에러가 나지 않는다
[System.Diagnostics.Conditional("UNITY_EDITOR")]

 

 

이거랑 용법은 비슷한테 인스펙터를 제어하는건 프로퍼티 드로워를 참고

https://wmmu.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EB%93%9C%EB%A1%9C%EC%9B%8C

 

유니티 프로퍼티 드로워

2021. 12. 16. 16:39

wmmu.tistory.com

 

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

유니티 커스텀 인스펙터  (0) 2020.05.19
UGui 관련  (0) 2020.05.19
안드로이드에서 뒤로가기 버튼을 누르면 종료됨  (0) 2020.05.19
posted by 모카쨩
2020. 5. 19. 21:34 Unity/C#

 

 

아래건 일정시간뒤 지정한 룸으로 이동하는 코드

 

 

근데 이따구로 짜지말고 코루틴으로 짜시길

 

 

 

슬라이더로 애니메이터 시간을 조정

1e+08은 100000000이고 1e-08은 0.00000001임

0으로 하면 플레이 시간이 무한대로 되니까 이렇게 한것, 그래도 190년동안 지켜봐야 애니메이션이 끝나니까 

일반적으론 지장없음, 그때쯤이면 유니티가 망할듯

rebind가 먼저오고 update가 나중에 와야함 여기서update는 해당시간에서 재생하겠다는 의미임

 

 

버튼을 누른거로 쳐줌

GetComponent<Button>().onClick.Invoke();

 

버튼에 리스터너 추가

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Choice : MonoBehaviour
{

    public Button button;
    List<Button> buttonClones= new List<Button>();


    public string folderPath="/Spreadsheets";
    //public string[] filePaths;
    public void PressButton(string filePath)
    {
        Debug.Log($"PressButton({filePath})");
    }
    // Start is called before the first frame update
    void Start()
    {
        button.gameObject.SetActive(false);

        
        var filePaths = System.IO.Directory.GetFiles($"{Application.persistentDataPath + folderPath}");
        var fileNames = System.Array.ConvertAll(filePaths,x=> System.IO.Path.GetFileNameWithoutExtension(x));



        for (int i = buttonClones.Count; i < fileNames.Length; i++)
        {
            var gameObject = Instantiate(button.gameObject, button.transform.parent);
            gameObject.SetActive(true);
            gameObject.GetComponentInChildren<Text>().text= $"{fileNames[i]}";
            var filePath = filePaths[i];
            gameObject.GetComponent<Button>().onClick.AddListener(() => PressButton(filePath)); //직접참조하지 말고 지역변수를 만들어서 할당
            buttonClones.Add(gameObject.GetComponent<Button>());
        }
    }

    // Update is called once per frame
    void Update()
    {
    }
}

다른 버전

더보기
public static int selectWeaponIndex=0;
public GameObject selectButton;
 List<GameObject> selectButtons= new List<GameObject>();
// Start is called before the first frame update
void Start()
{
    var length = selectButton.GetComponentInChildren<WeaponSystem>().weapons.Length;
    for (int i = 0; i < length; i++)
    {
        var instant=Instantiate(selectButton, selectButton.transform.parent);
        instant.GetComponentInChildren<WeaponSystem>().weaponIndex = i;
        var index = i;
        instant.GetComponent<Button>().onClick.AddListener(() => PressButton(index)); //직접참조하지 말고 지역변수를 만들어서 할당
        selectButtons.Add(instant);
    }
    selectButton.SetActive(false);
}
public void PressButton(int index)
{
    selectWeaponIndex = index;
    Debug.Log($"PressButton({index})");
}

 

 

 

 

 

2행 grid layout group (열 column,행 row)

 

 

 

 

 

 

 

ugui에 3d 넣기

https://wmmu.tistory.com/entry/ugui%EC%97%90-3d-%EB%84%A3%EA%B8%B0

 

ugui에 3d 넣기

결과물 화면비율 아무리 바꿔도 잘 된다 가로기준이라는거만 빼면 좋음

wmmu.tistory.com

 

 

 

 

 

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

유니티 어트리뷰트  (0) 2020.05.19
안드로이드에서 뒤로가기 버튼을 누르면 종료됨  (0) 2020.05.19
2D용 LookatTarget  (0) 2020.05.19
posted by 모카쨩
2020. 5. 19. 21:26 Unity/C#

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

UGui 관련  (0) 2020.05.19
2D용 LookatTarget  (0) 2020.05.19
충돌 계산 스크립트  (0) 2017.12.17
posted by 모카쨩
2020. 5. 19. 21:22 Unity/C#

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

안드로이드에서 뒤로가기 버튼을 누르면 종료됨  (0) 2020.05.19
충돌 계산 스크립트  (0) 2017.12.17
유니티 각도계산 모음  (0) 2017.11.06
posted by 모카쨩
2017. 12. 17. 21:55

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

2017. 11. 6. 14:54 Unity/C#

좌표계산

https://wmmu.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-%EC%A2%8C%ED%91%9C%EA%B3%84%EC%82%B0-%EB%AA%A8%EC%9D%8C

 

결과값이 좌표일 경우에는 위 링크로

결과값이 각도일 경우에는 이 글을 이용

 

 

 

pos1에서 pos2에대한 각도

Vector3 relativePos = pos2-pos1; 
Quaternion rotation = Quaternion.LookRotation (relativePos, Vector3.up );

 

 

상대 회전각

dir_speed=target.transform.rotation*Quaternion.Inverse(dir_previous);

 

상대 회전각2

a에서 b에대한 각도(위와 같음)

var a = Quaternion.Euler(0, 15, 0);
var b = Quaternion.Euler(0, 20, 0);
Debug.DrawLine(Vector3.zero, a * Vector3.forward, Color.red);
Debug.DrawLine(Vector3.zero, b * Vector3.forward, Color.blue);
Debug.DrawLine(Vector3.zero, (Quaternion.Inverse(a) * b) * Vector3.forward, Color.green);

 

상대회전각3

테스트는 안 해봄

var rotRel=Quaternion.FromToRotation(fromDir,ToDir);

 

각도 반전

var rotInverse=Quaternion.Inverse(transform.rotation);

 

 

 

 

speed = Quaternion.euler (0,0,0) * new vector3(0,0,0);  //len_vec과 동일

 

 

pDir(pointDirection)

2D계산용
수학계산을 이용한다. 일반적으로는 아래의 SignedAngle사용

    float PointDirection(Vector2 vec2)
    {
        vec2 = vec2.normalized;
        float offset;
        if (vec2.x > 0)
        {
            if (vec2.y > 0)
            {
                offset = 0;
            }
            else
            {
                var t = vec2.x;
                vec2.x = -vec2.y;
                vec2.y = t;

                offset = 270;
            }
        }
        else
        {
            if (vec2.y > 0)
            {
                var t = vec2.x;
                vec2.x = vec2.y;
                vec2.y = -t;

                offset = 90;
            }
            else
            {
                vec2.x = -vec2.x;
                vec2.y = -vec2.y;

                offset = 180;
            }
        }
        if (vec2.x == 0)
        {
            return 0;
        }
        return (Mathf.Atan(vec2.y / vec2.x) * Mathf.Rad2Deg) + offset;
    }

 

 

 

 

PDir

3D계산

var direction = Quaternion.LookRotation(pos2- pos1, Vector3.up);

 

 

PDir2D

좌현이 기준각도라서

Vector2.right를 좌현에 두고 쓰면 겜메랑 똑같이 나온다

Debug.Log(Vector2.SignedAngle(Vector2.zero, Vector2.up)); //0
Debug.Log(Vector2.SignedAngle(Vector2.zero, Vector2.down)); //0
Debug.Log(Vector2.SignedAngle(Vector2.zero, Vector2.left)); //0
Debug.Log(Vector2.SignedAngle(Vector2.zero, Vector2.right)); //0

Debug.Log(Vector2.SignedAngle(Vector2.right, Vector2.up)); //90
Debug.Log(Vector2.SignedAngle(Vector2.right, Vector2.down)); //-90
Debug.Log(Vector2.SignedAngle(Vector2.right, Vector2.left)); //180
Debug.Log(Vector2.SignedAngle(Vector2.right, Vector2.right)); //0

Debug.Log(Vector2.SignedAngle(Vector2.up, Vector2.up)); //0
Debug.Log(Vector2.SignedAngle(Vector2.up, Vector2.down)); //180
Debug.Log(Vector2.SignedAngle(Vector2.up, Vector2.left)); //90
Debug.Log(Vector2.SignedAngle(Vector2.up, Vector2.right)); //-90

 

 

Vector2.Angle 예제

Debug.Log(Vector2.Angle(Vector2.zero, Vector2.up)); //0
Debug.Log(Vector2.Angle(Vector2.zero, Vector2.down)); //0
Debug.Log(Vector2.Angle(Vector2.zero, Vector2.left)); //0
Debug.Log(Vector2.Angle(Vector2.zero, Vector2.right)); //0

Debug.Log(Vector2.Angle(Vector2.right, Vector2.up)); //90
Debug.Log(Vector2.Angle(Vector2.right, Vector2.down)); //90
Debug.Log(Vector2.Angle(Vector2.right, Vector2.left)); //180
Debug.Log(Vector2.Angle(Vector2.right, Vector2.right)); //0

Debug.Log(Vector2.Angle(Vector2.up, Vector2.up)); //0
Debug.Log(Vector2.Angle(Vector2.up, Vector2.down)); //180
Debug.Log(Vector2.Angle(Vector2.up, Vector2.left)); //90
Debug.Log(Vector2.Angle(Vector2.up, Vector2.right)); //90

 

DeltaAngle예제

-179.9~180각도 Normalize용 (정규화)

일반적으론 좌현을 0으로 두고 쓰면 된다

Debug.Log(Mathf.DeltaAngle(0, -270)); //90
Debug.Log(Mathf.DeltaAngle(0, -180)); //180
Debug.Log(Mathf.DeltaAngle(0, -90)); //-90
Debug.Log(Mathf.DeltaAngle(0, 0)); //0
Debug.Log(Mathf.DeltaAngle(0, 90)); //90
Debug.Log(Mathf.DeltaAngle(0, 180)); //180
Debug.Log(Mathf.DeltaAngle(0, 270)); //-90

Debug.Log(Mathf.DeltaAngle(90, -270)); //0
Debug.Log(Mathf.DeltaAngle(90, -180)); //90
Debug.Log(Mathf.DeltaAngle(90, -90)); //180
Debug.Log(Mathf.DeltaAngle(90, 0)); //-90
Debug.Log(Mathf.DeltaAngle(90, 90)); //0
Debug.Log(Mathf.DeltaAngle(90, 180)); //90
Debug.Log(Mathf.DeltaAngle(90, 270)); //180

 

 

각도정규화 

v1

더보기

 겜메 시절에 썼던거

public double d_set(double _Dir)
{
    if(_Dir<0d)
    {
        _Dir=360d-((-_Dir)%360d);
    }
    if(_Dir>=360d)
    {
        return _Dir%360d;
    }
    return _Dir;
}

 

v2

dir = (dir % 360f + 360f) % 360f;

 

v3

dir = Mathf.Repeat(dir, 360f);

 

 

각도정규화 (쉐이더용)

0~1로 정규화 한다

dir = frac(dir);

 

 

 

 

 

 

Dot예제

각도 연산을 바로 인풋으로 받아들일때 쓰면 편하다

Debug.Log(Vector2.Dot(Vector2.zero, Vector2.up)); //0
Debug.Log(Vector2.Dot(Vector2.zero, Vector2.down)); //0
Debug.Log(Vector2.Dot(Vector2.zero, Vector2.left)); //0
Debug.Log(Vector2.Dot(Vector2.zero, Vector2.right)); //0

Debug.Log(Vector2.Dot(Vector2.right, Vector2.up)); //0
Debug.Log(Vector2.Dot(Vector2.right, Vector2.down)); //0
Debug.Log(Vector2.Dot(Vector2.right, Vector2.left)); //-1
Debug.Log(Vector2.Dot(Vector2.right, Vector2.right)); //1

Debug.Log(Vector2.Dot(Vector2.up, Vector2.up)); //1
Debug.Log(Vector2.Dot(Vector2.up, Vector2.down)); //-1
Debug.Log(Vector2.Dot(Vector2.up, Vector2.left)); //0
Debug.Log(Vector2.Dot(Vector2.up, Vector2.right)); //0

 

 

두 벡터간 각도차이

Vector3.Angle(ray.direction, Camera.main.transform.forward)

 

특정 시야각 안에 들어왔는지 검사


bool IsInFOV(Vector3 position, float fovRatio)
{
    var cam = Camera.main;
    if (cam == null)
    {
        return false;
    }
    var direction = position - cam.transform.position;
    var angle = Vector3.Angle(cam.transform.forward, direction);
    var fov = cam.fieldOfView * fovRatio;
    if (angle > fov)
    {
        return false;
    }
    return true;
}

 

특정 시야각 안에 들어왔는지 검사2

targetingCircle.GetComponent<Image>().color = Color.white;
targetingCircle.GetComponent<FovToRectsize>().fov = GetWeapon().GetComponent<Gun>().spread * 2;
var fov = targetingCircle.GetComponent<FovToRectsize>().fov;
var targets = GameSystem.GetInGameOtherCharacters();
var cam = Camera.main;
var targeting = false;
foreach (var target in targets)
{
    Debug.DrawLine(transform.position, target.transform.position, Color.cyan);
    var directionToTarget = target.transform.position - cam.transform.position;
    var angle = Vector3.Angle(cam.transform.forward, directionToTarget);
    if (angle > fov)
    {
        continue;
    }

    var humanoidAnimatorController = target.GetComponentInChildren<HumanoidAnimatorController>();


    //디버깅이 원활하도록 배열로 한번에 안 만들고 하나씩 추가함
    var targetPoses = new List<Vector3>();
    targetPoses.Add(target.transform.position);
    targetPoses.Add(humanoidAnimatorController.GetBoneTransform(HumanBodyBones.Hips).position);
    targetPoses.Add(humanoidAnimatorController.GetBoneTransform(HumanBodyBones.Head).position);

    foreach (var targetPos in targetPoses)
    {
        if (Physics.Raycast(cam.transform.position, targetPos - cam.transform.position, out RaycastHit hit, maxDistance: 100))
        {
            Debug.DrawRay(cam.transform.position, targetPos - cam.transform.position, Color.red);
            if (hit.transform.tag == "Player")
            {
                Debug.DrawLine(targetPos, targetPos + Vector3.up, Color.red);
                targeting = true;
                break;
            }
        }
    }
    if (targeting)
    {
        break;
    }
}
{
    //정중앙에 보고 있는게 닿았는지 검사
    if (Physics.Raycast(cam.transform.position, cam.transform.forward, out RaycastHit hit))
    {
        Debug.DrawRay(cam.transform.position, cam.transform.forward, Color.red);
        if (hit.transform.tag == "Player")
        {
            targeting = true;
        }
    }
}
if (targeting)
{
    targetingCircle.GetComponent<Image>().color = new Color(1, 0.5f, 0.5f);
}

 

 

 

맞은 각도 표시

firePosition은 발사지점

var relativePosition = Quaternion.Inverse(transform.rotation) * (firePosition - transform.position);
var relativePosition2D = new Vector2(relativePosition.x, -relativePosition.z);

var rot = Quaternion.Euler(0, 0, Vector2.SignedAngle(relativePosition2D, Vector2.right));
damageUI.transform.rotation = rot;

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

충돌 계산 스크립트  (0) 2017.12.17
유니티 함수 정리  (0) 2017.07.02
c# list(리스트) 관련  (0) 2017.03.23
posted by 모카쨩
2017. 7. 2. 22:48 Unity/C#
Application.targetFrameRate=60;  //룸스피드를 60프레임으로 맞춤
Application.runInBackground=true;   //백그라운드상에서도 동작하게 한다
DontDestroyOnLoad(this.gameObject);   //룸을 이동해도 오브젝트가 지워지지 않는다
UnityEngine.SceneManagement.SceneManager.LoadScene(룸);   //Application.LoadLevel대신 들어온 녀석, 룸을 이동한다
Application.Quit (); //종료



월드 좌표: 게임내 가상좌표, 편의를 위해 기본좌표계라고 사용
스크린상 좌표: 좌x0, 우x픽셀길이, 상y픽셀높이, 하y0 
Input.GetKey (키보드 번호): 키보드가 눌렸는지를 반환한다. 키보드 번호는 KeyCode에 따라 좌우된다.
Input.GetMouseButton(버튼 번호): 마우스가 클릭했는지를 반환한다. 0은 왼쪽 1은 오른쪽 2는 가운데
Input.GetAxis("Vertical") : 정의된 방향키의 위아래 값을 반환한다 -1이 위쪽
Input.GetAxis("Horizontal") : 정의된 방향키의 좌우 값을 반환한다 -1이 왼쪽
Input.mousePosition : 마우스의 스크린상좌표를 반환한다
Camera.main.ScreenToWorldPoint(좌표) : 스크린상 좌표를 기본좌표계로 변환
Camera.main.WorldToScreenPoint(좌표) : 기본좌표를 스크린상 좌표로 변환

Screen.width //화면가로해상도를 반환
Screen.height //화면세로해상도를 반환
screenHeightCentimeter = Display.main.systemHeight / ((Screen.dpi==0? 96:Screen.dpi) / 2.54f); //화면 세로 Cm높이를 반환
Screen.currentResolution.height //모니터 높이 해상도를 반환(Screen.height와 다른점은 창이 작아져도 최대값을 반환함)
Display.main.renderingWidth //현재 렌더링 되는 디스플레이 사이즈, screen.width랑 같다고 보면 된다
Display.main.systemWidth //물리적인 디스플레이 사이즈, 스크린 사이즈가 바뀌어도 기기레퍼런스값을 가져오므로 불변이다.


float canvasHei = GetComponentInParent<Canvas>().GetComponent<RectTransform>().rect.height; //현재 캔버스의 높이를 반환
(1 / screenHeightCentimeter) * canvasHei //1센치에 대한 캔버스 픽셀사이즈를 반환


//RectTransform계열
float wid = GetComponent<RectTransform>().sizeDelta.x; //rect.width와 동일
float wid = GetComponent<RectTransform>().rect.width; //sizeDelta.x와 동일
textUI.rectTransform.anchoredPosition.x //일반적으로 생각하는 rectTransform의 x좌표
textUI.rectTransform.localPosition.x //Anchors가 미적용된 x좌표, 가급적 사용자제
textUI.rectTransform.rect.x //작동안함, anchoredPosition써라




Physics2D.CircleCast(위치(vector2), 반지름, 각도(Vector2)) :  원충돌 검사 RaycastHit2D를 반환하고, (RaycastHit2D.transform!=null) 검사로 충돌했는지 확인가능

GetComponent<Rigidbody2D> ().AddRelativeForce (Vector2.right*1000f); //상대적인 정면을 향해 힘을 줌, 질량에 따라 바뀜
GetComponent<Rigidbody2D> ().velocity //속력을 반환



GetComponent<Rigidbody2D>().AddForce( (transform.position-target.position).normalized*-gravity); //특정방향으로 힘을 줌



Vector2.Distance(Vec2_A,Vec2_B); //벡터간의 길이값을 반환

Vector3.Distance(Vec3_A,Vec3_B); //벡터간의 길이값을 반환 3D


this.GetComponent<Renderer>().material.mainTexture  //렌더러의 텍스처

this.GetComponent<SpriteRenderer>().sprite  //렌더러의 스프라이트



GetComponent<AudioSource>().volume //게임오브젝트의 사운드 볼륨조절



GUI.Label (new Rect(x,y,wid,hei),text); draw_text와 같다



void OnGUI(){} //GUI계층의 함수를 사용할수 있다

void OnCollisionEnter2D(Collision2D col) //리지드바디2D가 충돌을 시작했을때 작동한다 OnCollisionStay2D는 항상 OnCollisionExit2D는 종료시,Collision을 Trigger로 바꾸면 트리거 작동 인수는 그대로

{

}

void OnCollisionStay(Collision col) //Enter와 다르게 항상 작동한다

{

}

GetComponent<Collider2D>().IsTouchingLayers() //충돌했는지 반환



Mathf.Clamp(value,min,max) //median함수와 동일함

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

유니티 각도계산 모음  (0) 2017.11.06
c# list(리스트) 관련  (0) 2017.03.23
c# list와 array속도 비교  (3) 2017.01.25
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입