Get it on Google Play


Wm뮤 :: 'Unity/C#' 카테고리의 글 목록 (4 Page)

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

Recent Comment

Archive


'Unity/C#'에 해당되는 글 63건

  1. 2021.06.01 유니티 오디오 관련 코드
  2. 2021.05.16 오큘러스 함수들
  3. 2021.04.12 유니티 에디터 윈도우
  4. 2021.01.24 코드 모음 사이트
  5. 2021.01.18 수학 Math
  6. 2021.01.17 화면관련
  7. 2021.01.15 c# 기본 문법
  8. 2020.12.24 MapBorder
2021. 6. 1. 15:27 Unity/C#
public static void WaveToMP3(string waveFileName, string mp3FileName, NAudio.Lame.LAMEPreset bitRate = NAudio.Lame.LAMEPreset.ABR_128)
{
    using (var reader = new NAudio.Wave.WZT.WaveFileReader(waveFileName))
    using (var writer = new NAudio.Lame.LameMP3FileWriter(mp3FileName, new NAudio.Wave.WZT.WaveFormat(), bitRate))
        reader.CopyTo(writer);
}
public void SaveMp3(string filePath,AudioClip clip)
{
    if (clip == null)
    {
        Debug.LogError("클립없음");
        return;
    }
    var tempPath = Application.temporaryCachePath + "/tempAudio";
    //Debug.Log(tempPath);
    SavWav.Save(tempPath, clip);
    //Debug.Log(filePath);
    WaveToMP3(tempPath, filePath);
    System.IO.File.Delete(tempPath);
}

 

볼륨 프로토 타입

    float GetVolume(float[] audioData, int index, int samplingRate)
    {
        if ((audioData == null) || (audioData.Length == 0))
        {
            return 0;
        }
        float checkTime = 0.05f;

        var startIndex = index;
        var length = Mathf.Min(audioData.Length - index, (int)(samplingRate * checkTime));
        var sliceArray = audioData.Skip(startIndex).Take(length).ToArray();
        //return System.Array.ConvertAll(sliceArray, x => Mathf.Abs(x)).Average();
        if ((sliceArray == null) || (sliceArray.Length == 0))
        {
            return 0;
        }
        return sliceArray.Max();
    }

 

 

 

 

 

 

 

현재 오디오소스의 볼륨을 가져옴

    public AudioSource audioSource;

    float GetVolume(float[] audioData, int index, int samplingRate)
    {
        if ((audioData == null) || (audioData.Length == 0))
        {
            return 0;
        }
        float checkTime = 0.05f;

        var startIndex = index;
        var length = Mathf.Min(audioData.Length - index, (int)(samplingRate * checkTime));
        var sliceArray = audioData.Skip(startIndex).Take(length).ToArray();
        //return System.Array.ConvertAll(sliceArray, x => Mathf.Abs(x)).Average();
        if ((sliceArray == null) || (sliceArray.Length == 0))
        {
            return 0;
        }
        return sliceArray.Max();
    }
    // Update is called once per frame
    void Update()
    {

        var clip = audioSource.clip;
        var ratio = audioSource.time / clip.length;
        var samplingRate = clip.frequency;
        int index = (int)(clip.samples * ratio / clip.channels);
        float[] audioData = new float[clip.samples * clip.channels];
        audioSource.clip.GetData(audioData, 0);
        float volume = GetVolume(audioData, index, samplingRate);
        //float volume2 = audioData[index] - audioData[Mathf.Max(0, index - 1)];


        var localScale = transform.localScale;
        localScale.x= volume;
        transform.localScale = localScale;
    }

 

wav로 저장

https://gist.github.com/darktable/2317063

var savePath = SFB.StandaloneFileBrowser.SaveFilePanel("Save File",directory:"", "defaultName", ".wav"); 
if (savePath == null)
{
    return;
}
SavWav.Save(savePath, clip);

 

 

mp3로 저장 (Unity3D-save-audioClip-to-MP3)

https://github.com/BeatUpir/Unity3D-save-audioClip-to-MP3

var savePath = SFB.StandaloneFileBrowser.SaveFilePanel("Save File",directory:"", "defaultName", ".mp3"); 
if (savePath == null)
{
    return;
}
EncodeMP3.convert(clip, savePath, bitRate: 128);

 

mp3로 저장 (Lame-For-Unity)

위에거보단 느리고 불안정

조심할점은 위의 Unity3D-save-audioClip-to-MP3와 충돌한다는 점이다

https://github.com/3wz/Lame-For-Unity

public static void WaveToMP3(string waveFileName, string mp3FileName, NAudio.Lame.LAMEPreset bitRate = NAudio.Lame.LAMEPreset.ABR_128)
{
    using (var reader = new NAudio.Wave.WZT.WaveFileReader(waveFileName))
    using (var writer = new NAudio.Lame.LameMP3FileWriter(mp3FileName, new NAudio.Wave.WZT.WaveFormat(), bitRate))
        reader.CopyTo(writer);
}
public void SaveMp3(string filePath,AudioClip clip)
{
    if (clip == null)
    {
        Debug.LogError("클립없음");
        return;
    }
    var tempPath = Application.temporaryCachePath + $"/tempAudio.wav";
    //Debug.Log(tempPath);
    SavWav.Save(tempPath, clip);
    //Debug.Log(filePath);
    WaveToMP3(tempPath, filePath);
    System.IO.File.Delete(tempPath);
}

 

 

 

윈도우에서 mp3로드

https://assetstore.unity.com/packages/tools/audio/audioimporter-146746

 

 

 

 

 

 

 

 

 

 

 

 

 

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

유니티 안드로이드 빌드관련 스크립트  (0) 2021.06.10
오큘러스 함수들  (0) 2021.05.16
유니티 에디터 윈도우  (0) 2021.04.12
posted by 모카쨩
2021. 5. 16. 12:51 Unity/C#

 

 

OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger, OVRInput.Controller.LTouch);

//얼마나 그랩이 당겨졌는지 반환

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

유니티 오디오 관련 코드  (0) 2021.06.01
유니티 에디터 윈도우  (0) 2021.04.12
코드 모음 사이트  (0) 2021.01.24
posted by 모카쨩
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 모카쨩
2021. 1. 24. 21:42 Unity/C#

www.delftstack.com/ko/howto/csharp/how-to-read-a-csv-file-and-store-its-values-into-an-array-in-csharp/

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

유니티 에디터 윈도우  (0) 2021.04.12
수학 Math  (0) 2021.01.18
화면관련  (0) 2021.01.17
posted by 모카쨩
2021. 1. 18. 16:35 Unity/C#

 

Xⁿ=Y 일때

n을 구하려면 log(Y) / log(X)                //로그
X를 구할려면 Sqrt(Y,n)                       //루트,제곱근, 여러개이면 거듭제곱근
Y를 구할려면 Pow(X,n) 혹은 Sqr(X,n)     //제곱,여러개이면 거듭제곱    

이상한 방법들

X를 구할때 보통을 sqrt를 써야하지만 인자를 1개만 받는 함수밖에 없을경우에
Pow(Y,1/n) //혹은 Sqr
이렇게 Pow를 써서 sqrt를 구할수도 있다
즉 Sqrt(x) = pow(x,1/2) 이다

 

Sqr계열

32의 5제곱근을 구할때

Sqr(32,1/5) //1은 고정숫자임

계산기 버전

 

 

 

 

log계열

 

//1024가 2의 몇승인지 구한다

Mathf.Log(1024,2)

다른버전

Mathf.Log(1024)/Mathf.Log(2)

계산기 버전

 

쓸모는 없지만

log(32)/5 = log(2)

이다

참고로 32는 2의 5제곱이다 즉

x^y=z일때

log(z)/y = log(x)

 

 

 

 

 

 

//npot를 최적의 2pot사이즈로 변경

wid=Mathf.Pow(2, Mathf.Round(Mathf.Log(texture.width, 2))));
hei=Mathf.Pow(2, Mathf.Round(Mathf.Log(texture.height, 2))));

/*
결과:
256->256
230->256
140->128
1031->1024
*/

 

 

 

 

원점에서의 거리

var len = sqrt(x*x + y*y);

 

 

x1,y1에서 x2,y2까지의 거리

 

 

 

 

 

 

 

Len과 dir을 이용하여 좌표를 구함

		public double d_set(double _Dir)
		{
			if(_Dir<0d)
			{
				_Dir=360d-((-_Dir)%360d);
			}
			if(_Dir>=360d)
			{
				return _Dir%360d;
			}
			return _Dir;
		}
		public double len_x(double _Len,double _Dir)
		{
			_Dir = d_set(_Dir);
			return _Len*Math.Cos(_Dir*Math.PI/180.0);
		}
        
		public double len_y(double _Len,double _Dir)
		{
			_Dir = d_set (_Dir);
			return _Len*Math.Sin(_Dir*Math.PI/180.0);
		}

 

 

pdir

x1,x2,y1,y2를 이용하여 각도를 구함

float2 center = 0.5;
float2 pos = i.uv.xy-center;
float2 dir  = ((atan2(pos.x,-pos.y)*2/3.14)/4+0.75)%1;

 

 

 

 

p1,p2,r,center를 이용하여 p3를 구하는 공식
챗GPT가 짜줬다

float2 FindIntersection(float2 p1, float2 p2, float R, float2 center)
{
    float2 dir = normalize(p2 - p1);
    float2 diff = p1 - center;

    // 원의 중심에서 선까지의 거리 d 계산
    float d = abs(diff.x * dir.y - diff.y * dir.x);

    // 만약 d가 R보다 크면 교점이 없음
    if (d >= R)
        return float2(0, 0);

    // L 계산: L = sqrt(R^2 - d^2)
    float L = sqrt(R * R - d * d);

    // 원의 중심에서 교점까지의 거리 h 계산: h = sqrt(R^2 - L^2)
    float h = sqrt(R * R - L * L);

    float2 midpoint = p1 + dot(center - p1, dir) * dir; // 선 위의 원의 중심에 수직인 점

    // 두 교점은 midpoint에서 ±L만큼 dir 방향으로 떨어져 있음
    float2 intersection1 = midpoint + L * dir;
    float2 intersection2 = midpoint - L * dir;

    // 이 예제에서는 두 교점 중 하나만 반환합니다.
    // 필요에 따라 두 교점 중 원하는 교점을 선택하여 반환하면 됩니다.
    return intersection1; 
}

 

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

코드 모음 사이트  (0) 2021.01.24
화면관련  (0) 2021.01.17
c# 기본 문법  (0) 2021.01.15
posted by 모카쨩
2021. 1. 17. 03:52 Unity/C#

 

 

 

 

모니터계열

public static Bitmap screenImg = new Bitmap(SystemInformation.VirtualScreen.Width
, SystemInformation.VirtualScreen.Height
, PixelFormat.Format32bppArgb);

public static Graphics graphicsScreenImg = Graphics.FromImage(screen_img);
//모니터 화면을 가져옴(전역변수에 담아둔다음 불러오는 형식)
public static System.Drawing.Bitmap GetScreen()
{
    graphicsScreenImg.CopyFromScreen(SystemInformation.VirtualScreen.X
        , SystemInformation.VirtualScreen.Y
        , 0
        , 0
        , SystemInformation.VirtualScreen.Size
        , CopyPixelOperation.SourceCopy);
    return screenImg;
}
//모니터화면을 가져옴(안정적이지만 호출시마다 메모리 사용량이 높음)
public static Bitmap GetScreenLS()
{

    Bitmap img = new Bitmap(SystemInformation.VirtualScreen.Width
            , SystemInformation.VirtualScreen.Height
            , PixelFormat.Format32bppArgb);

    Graphics graphics = Graphics.FromImage(img);
    graphics.CopyFromScreen(SystemInformation.VirtualScreen.X
        , SystemInformation.VirtualScreen.Y
        , 0
        , 0
        , SystemInformation.VirtualScreen.Size
        , CopyPixelOperation.SourceCopy);
    return img;
}
//모니터픽셀 가로
public static int GetScreenWidth()
{
    return SystemInformation.VirtualScreen.X;
}
//모니터픽셀 세로
public static int GetScreenHeight()
{
    return SystemInformation.VirtualScreen.Y;
}

 

 

 

2021년 기준 화면비

Z폴드2 (5:4)

Z플립3 (22:9)

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

수학 Math  (0) 2021.01.18
c# 기본 문법  (0) 2021.01.15
MapBorder  (0) 2020.12.24
posted by 모카쨩
2021. 1. 15. 00:49 Unity/C#

 

 

구조체

더보기
public struct mVec3
    {
        public float x, y, z;
        public float Length
        {
            get
            {
                return (float)(Math.Sqrt((x * x) + (y * y) + (z * z)));
            }
            set
            {
                //float _t=Length*value;
                //float _t=value/(float)(Math.Sqrt((x*x)+(y*y)+(z*z)));
                if (Length <= 0)
                {
                    z = value;
                }
                else
                {
                    float _t = value / Length;
                    x *= _t;
                    y *= _t;
                    z *= _t;
                }
            }
        }
public static mVec3 forward //절대적
{
 get
 {
  return new mVec3(0f,0f,1f);
 }
}
public mVec3 up //상대적
{
 get
 {
  return new mVec3((Quaternion.Euler( this.x,this.y,this.z) * Quaternion.Euler(90f,0f,0f)).eulerAngles);
  //return mScript.len_vec(this);
 }
}
        
        public mVec3() : this(1,2,3)//생성자 (x:1,y:2,z:3)
        {

        }
        public mVec3(float X, float Y, float Z)//생성자
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
        public static mVec3 operator ++(mVec3 _Vec)
        {
            _Vec.x++;
            _Vec.y++;
            _Vec.z++;
            return _Vec;
        }
        public static mVec3 operator /(mVec3 _Vec1, mVec3 _Vec2)
        {
            _Vec1.x /= _Vec2.x;
            _Vec1.y /= _Vec2.y;
            _Vec1.z /= _Vec2.z;
            return _Vec1;
        }
        public static explicit operator mVec4(mVec3 _this) //명시적 형변환, 암시적은 implicit
        {
            mVec4 _return;
            _return.x=_this.x;
            _return.y=_this.y;
            _return.z=_this.z;
            _return.w=0;
            return _Vec;
        }
        

        public static bool operator ==(mVec3 _Vec1, mVec3 _Vec2)
        {
            foreach (var field in typeof(mVec3).GetFields())
            {
                if (field.GetValue(_Vec1) != field.GetValue(_Vec2))
                {
                    return false;
                }
            }
            return true;
        }
        public static bool operator !=(mVec3 _Vec1, mVec3 _Vec2)
        {
            return !(questionDictionary1== questionDictionary2);
        }
}
사용시
        //public static mVec3 zero(0f,0f,0f);

 

 

Enum

    public enum UpperPath
    {
        persistentDataPath
            , dataPath
            , streamingAssetsPath
            , temporaryCachePath
    };

 

Enum 길이 반환

int enumCount=System.Enum.GetValues(typeof(EnumName)).Length;
        Category[] openCategorysIndexes = (Category[])System.Enum.GetValues(typeof(Category));

 

 

namespace가 아닌 class using

using static SampleClass;

 

using문

using (var streamReader = new System.IO.StreamReader(response))
{
    string result = streamReader.ReadToEnd();
    streamReader.Close();
    return result;
}

 

 

 

 

자주쓰는데 은근 겁나 까먹음

try
{

}
catch(Exception ex)
{
	Debug.Log(ex.ToString());
}

 

 

 

 

변수이름

string 변수명=nameof(변수);

타입 이름

typeof(AudioClip).Name

 

 

 

c#버전 #define

public const float PointMax = 2;
public float Point = PointMax;

 

 

C#의 실제 #define

버전관리할때 유용함

#define Ver1000
#define Ver1001

#if Ver1000
    //여기서 동작함
#elif Ver1001
    //Ver1001일때 작동함
#else
    //그것도 아닐때
#endif

 

 

 

 

///함수주석

    /// <summary>
    /// 이름을 GUI에 표시함
    /// </summary>
    /// <param name="wordDictionary">이름</param>
    /// <param name="wid">가로크기</param>
    /// <param name="hei">세로크기</param>
    void DrawWordDictionary(string Name, int wid, int hei)
    {
    }

 

 

널은 안됨

class NotNullContainer<T> where T : notnull
{
}

 

new한정자

new가 붙은거만 넣을수 있음

    public static T GetClass<T>(string text) where T : new()
    {
    	if(text=="ok")
        {
            var targetClass = new T();
            return targetClass;
        }
        else
        {
            return null;
        }
    }

 

 

is 연산자

어디서 온건지 알 수 없는 obj등을 처리할 때 쓰인다

if ((objData is Dictionary<string, object>)==false)
{
	Debug.LogError("objData는 Dictionary<string, object>가 아닙니다");
	return;
}

//아래와 동일함

if ((objData.GetType() == typeof(Dictionary<string, object>))==false)
{
	Debug.LogError("objData는 Dictionary<string, object>가 아닙니다");
	return;
}

 

 

as 연산자

캐스팅 연산자인데 좀 복잡함 아래 참고

서로 동일한 코드를 나타내고 있다

string text= obj as string;

//위아래 동일함

string text;
if (obj is string)
{
    text = (string)obj;
}
else
{
    text = null;
}

 

 

if else 간소화 (남용은 금지, 복수로 쓰게될경우 가독성이 개판된다)

bool A;
if (B)
{
   A = C;
}
else
{
   A = D;
}


//위아래 동일

bool A=B?C:D;

 

null체크 간소화

if (A != null)
{
    if (B != null)
    {
        return C;
    }
}
return null;


//위아래 동일


return A?.B?.C;

 

?[]연산 에러발생시 null반환

다만 인덱스 오류는 캐치가 안 된다

string text = null;
if (array!=null)
{
    text = array[1];
}

//위아래 동일

var text = array?[1];

 

 

 

아래건 동일분기 처리를 좀 알아봐야 겠다

switch 간소화 (유니티 안됨, 비주얼스튜디오 2019 자동화 안됨)

switch(condition)
{
   case 1:
      A=B;
      break;
   case 2:
      A=C;
      break;
   default:
      A=D;
     break;
}

//위아래 동일


condition switch
{
    1 => A=B;
    2 => A=C;
    _ => A=D;
}

 

 

 

 

튜플

    void Start()
    {
        var (min, max) = FindMinMax(1, 2, 3, 4);
        Debug.Log("min: " + min);
        Debug.Log("max: " + max);
    }
    (int min, int max) FindMinMax(params int[] input)
    {
        var min = Mathf.Min(input);
        var max = Mathf.Max(input);
        return (min, max);
    }

 

여러개 리턴할때 사용

 

유니티도 된다

 

 

 

 

??연산

null처리할때 좋음

아래 네개 모두 동일한 코드이다

string a = null;
Debug.Log(a ?? "ABC"); //ABC반환
a = "a";
Debug.Log(a ?? "BCD"); //a반환

//위아래 동일

string a = null;
Debug.Log(a is string ? a:"ABC"); //ABC반환
a = "a";
Debug.Log(a is string ? a:"BCD"); //a반환

//위아래 동일

string a = null;
Debug.Log(a==null ? "ABC":a); //ABC반환
a = "a";
Debug.Log(a==null ? "BCD":a); //a반환


//위아래 동일

string a = null;
if(a!=null)
{
	Debug.Log(a);
}
else
{
	Debug.Log("ABC");
}
a = "a";
if(a!=null)
{
	Debug.Log(a);
}
else
{
	Debug.Log("BCD");
}

 

 

인덱스 체크 간소화

근데 어차피 쓰려면 null체크 추가로 들어가서 그렇게 효율적이진 않음
오히려 협업할때는 누구나 알기쉬운 위쪽이 나을수도 있겠다


if((index >= 0)&&(index < array.Length))
{
    var item = array[index];
    //작동할 코드
}


//위아래 동일

var item = array.ElementAtOrDefault(index);
if(item != null)
{
    //작동할 코드
}

 

 

 

로컬함수

외부로 표출될 필요가 없는 함수 작성시 매우매우 유용하다.

특히 최장점은 같은 이름의 함수를 여러군데서 쓸수있다는 점

함수를 사용할때마다 생성하는 방식인지

성능을 절약하기 위해 static을 붙이라는 문구가 뜨는데 유니티 2019에서는 미지원이다

void SampleFunction()
{
    Debug.Log(LocalFunction("test")); //long text
    Debug.Log(LocalFunction("te")); //short text
    Debug.Log(LocalFunction("")); //short text


    string LocalFunction(string text)
    {
        if(text.Length>2)
        {
            return "long text";
        }
        return "short text";
    }
}

 

 

 

모든 스크립트에 using을 적용

몰론 함부로 쓰면 ㅈ된다

global using System;

 

 

 

함수내부 조건식 Predicate

 public static class Array
{
    //Array.FindIndexAll(arr,x=>x>1);
    //혹은 arr.FindIndexAll(x=>x>1);
    public static int[] FindIndexAll<T>(this T[] array, System.Predicate<T> match)
    {
        var indexList = new List<int>();
        for (int i = 0; i < array.Length; i++)
        {
            if (match.Invoke(array[i]))
            {
                indexList.Add(i);
            }
        }
        return indexList.ToArray();
    }
    
    //2개인자
    //Array.FindAll(arr,x=>x.Item1>x.Item2)
    public static int[] FindAll<T>(T[] array, System.Predicate<(T previous,T target)> match)
    {
        var indexList = new List<int>();
        for (int i = 0; i < array.Length; i++)
        {
            if (match.Invoke((array[i-1],array[i])))
            {
                indexList.Add(i);
            }
        }
        return indexList.ToArray();
    }
}

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

화면관련  (0) 2021.01.17
MapBorder  (0) 2020.12.24
리플렉션  (0) 2020.12.23
posted by 모카쨩
2020. 12. 24. 01:31 Unity/C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapBorder : MonoBehaviour {

	private void OnDrawGizmos()
	{
		Gizmos.DrawWireCube(borderCenter, borderSize);
	}
	public enum DropOption
	{
		None
		, Respawn
		, Destroy
	}
	public DropOption dropOption = DropOption.Respawn;

	public Vector3 borderCenter = Vector3.zero;
	public Vector3 borderSize = new Vector3(200,100,200);
	public Transform respawnPoint;
	Vector3 firstPosition;
	Quaternion firstRotation;
	// Use this for initialization
	void Start ()
	{
		firstPosition = transform.position;
		firstRotation = transform.rotation;
	}
	
	// Update is called once per frame
	void Update () {

		var pos = transform.position;
		pos.x = Mathf.Clamp(pos.x, borderCenter.x - borderSize.x, borderCenter.x + borderSize.x );
		pos.y = Mathf.Min(pos.y, borderCenter.y + borderSize.y );
		pos.z = Mathf.Clamp(pos.z, borderCenter.z - borderSize.z , borderCenter.z + borderSize.z);



		transform.position = pos;
		if (transform.position.y<borderCenter.y- borderSize.y )
		{
			switch (dropOption)
			{
				case DropOption.None:
					break;
				case DropOption.Respawn:
					if (respawnPoint == null)
					{
						transform.position = firstPosition;
						transform.rotation = firstRotation;
					}
					else
					{
						transform.position = respawnPoint.transform.position;
						transform.rotation = respawnPoint.transform.rotation;
					}
					break;
				case DropOption.Destroy:
					Destroy(gameObject);
					break;
				default:
					break;
			}
		}
	}
}

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

c# 기본 문법  (0) 2021.01.15
리플렉션  (0) 2020.12.23
그래디언트효과  (0) 2020.10.20
posted by 모카쨩

  • total
  • today
  • yesterday

Recent Post

저사양 유저용 블로그 진입