Get it on Google Play


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

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

Recent Comment

Archive


2024. 8. 23. 06:30 Unity/C#


Root를 제외한 경로반환

v1 ~ v3

더보기


가령 Root/armature/Hips는 /armature/Hips가 된다

string ArmaturePath(Transform bone)
{
    var rootName = bone.transform.root.name;
    var hierarchyPath = bone.transform.GetHierarchyPath();
    return hierarchyPath.Substring(rootName.Length, hierarchyPath.Length - rootName.Length);
}

 

 


Root를 제외한 경로반환 v2 (상대경로)

인자를 하나 더 받고 안정성을 높였다

https://gist.github.com/ahzkwid/c89b626c0e7bace5cc317901b524672e

static string RelativePath(Transform target, Transform root = null)
{
    var rootName = "";
    var hierarchyPath = "";


    if (root != null)
    {
        try
        {
            rootName = SearchUtils.GetHierarchyPath(root.gameObject, false);

        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex);
            Debug.LogError(root.ToString() + "nothing root");
            //Debug.LogError(bone.name + "는 root가 없음");
            throw;
        }
    }
    try
    {
        //hierarchyPath = bone.GetHierarchyPath();
        hierarchyPath = SearchUtils.GetHierarchyPath(target.gameObject, false);
    }
    catch (System.Exception ex)
    {
        Debug.LogError(ex);
        Debug.LogError(target.ToString() + "nothing GetHierarchyPath");
        throw;
    }

    var startIndex = rootName.Length;

    return hierarchyPath.Substring(startIndex, hierarchyPath.Length - startIndex);
}

 

v3

static string RelativePath(Transform target, Transform root = null)
{
    var rootName = "";
    var hierarchyPath = "";


    if (root != null)
    {
        try
        {
            rootName = SearchUtils.GetHierarchyPath(root.gameObject, false);

        }
        catch (System.Exception ex)
        {
            Debug.LogError(ex);
            Debug.LogError(root.ToString() + "nothing root");
            //Debug.LogError(bone.name + "는 root가 없음");
            throw;
        }
    }
    try
    {
        //hierarchyPath = bone.GetHierarchyPath();
        hierarchyPath = SearchUtils.GetHierarchyPath(target.gameObject, false);
    }
    catch (System.Exception ex)
    {
        Debug.LogError(ex);
        Debug.LogError(target.ToString() + "nothing GetHierarchyPath");
        throw;
    }

    var startIndex = rootName.Length;

    if (rootName.Length > hierarchyPath.Length)
    {
        Debug.LogWarning("rootName.Length > hierarchyPath.Length");
        Debug.LogWarning($"{rootName} > {hierarchyPath}");
        return null;
    }

    if (hierarchyPath.Substring(0, rootName.Length) != rootName)
    {
        Debug.LogWarning("hierarchyPath.Substring(0, rootName.Length) != rootName");
        Debug.LogWarning($"{rootName} != {hierarchyPath}.Substring(0, rootName.Length)");
        return null;
    }

    try
    {
        return hierarchyPath.Substring(startIndex, hierarchyPath.Length - startIndex);
    }
    catch (System.Exception ex)
    {
        Debug.LogError(ex);
        Debug.LogError($"{hierarchyPath} - {rootName}");
        throw;
    }
}

 

 

v4

경우에 따라 앞에 슬래시는 없애도 된다

var relativePath = "/"+Path.GetRelativePath(rootpath, path);

 

 

 

 

 

 

하이어라키 경로 반환

var path = SearchUtils.GetHierarchyPath(gameObject, false);

 

 

 

패스 병합

Replace 붙은 이유는 유니티는 '/'를 쓰는데 일부 로직에서 '\'를 인식 못하기 때문

var path = Path.Join(parentPath, childPath).Replace("\\", "/");

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

OnSceneGUI 관련코드  (0) 2024.07.11
유니티 라이트 레졸루션 개별설정  (0) 2024.05.12
유니티 프리팹 드래그 드랍  (0) 2024.05.09
posted by 모카쨩
2024. 7. 11. 19:30 Unity/C#

 

 

 

 

 

OnDrawGizmos처럼 상시동작하는점이 비슷하지만

OnDrawGizmos는 기즈모 드로우 옵션이 켜져있을때에만 동작하므로

기능코드는 가급적 OnSceneGUI에 넣는것이 좋다

 

 

 

1. Static에서 FindObjectsOfType를 이용해 가져와서 처리하는 방식

gist : https://gist.github.com/ahzkwid/3294e9d4cf3980ae2d1c135123db145c

public class SampleClass : MonoBehaviour
{
  static void OnSceneGUI(SceneView sceneView)
  {
      foreach (var sampleClass in FindObjectsOfType<SampleClass>())
      {
          if (sceneView.camera != null)
          {
              var sceneCamera = sceneView.camera;
              //CameraCode
          }
          //otherCode
      }
  }
}
//OtherSample: https://gist.github.com/ahzkwid/6647d3aec625afe96c54bb38b2671c72

 

 

 

 

 

2. SceneView.duringSceneGui에서 이벤트를 받는 방식

원문링크 : https://forum.unity.com/threads/solved-how-to-start-draganddrop-action-so-that-sceneview-and-hierarchy-accept-it-like-with-prefabs.822531/

아래 코드는 내가 만든게 아니고 위 링크에서 가져와 간소화 한것일뿐이다

[ExecuteInEditMode]
public class SampleClass : MonoBehaviour
{
     void OnEnable()
    {
        SceneView.duringSceneGui += OnSceneGUI;
        EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
    }

     void OnDisable()
    {
        SceneView.duringSceneGui -= OnSceneGUI;
        EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyGUI;
    }
     void OnSceneGUI(SceneView obj)
    {
        HandleDragAndDropEvents();
    }

     void OnHierarchyGUI(int instanceID, Rect selectionRect)
    {
        HandleDragAndDropEvents();
    }
     void HandleDragAndDropEvents()
    {
        if (Event.current.type == EventType.DragUpdated)
        {
            OnDragUpdated();
        }
        if (Event.current.type == EventType.DragPerform)
        {
            OnDragPerform();
        }
    }
    void OnDragUpdated()
    {
        Debug.Log("OnDragUpdated()");
    }
    void OnDragPerform()
    {
        Debug.Log("OnDragPerform()");
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

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

유니티 오브젝트 경로 관련  (0) 2024.08.23
유니티 라이트 레졸루션 개별설정  (0) 2024.05.12
유니티 프리팹 드래그 드랍  (0) 2024.05.09
posted by 모카쨩
2024. 5. 12. 12:01 Unity/C#

 

 

 

 

 

 

 

 

 

 

 

유니티 2022.3.22.f1 이후의 경우

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


유니티 2022.3.22.f1 이전의 경우는 아래 스크립트 적용 

 

 

 

SettingLightResolution.unitypackage
0.00MB

 

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

[ExecuteAlways]
public class SettingLightResolution : MonoBehaviour
{
    public Light light;
    public int resolution = 256;
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        if (light==null)
        {
            return;
        }
        light.shadowCustomResolution = resolution;
#if UNITY_EDITOR
        UnityEditor.EditorUtility.SetDirty(light);
#endif
    }
}



어쩌다보니 만들게 됨

 

 

 

 

 

 

 

 

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

OnSceneGUI 관련코드  (0) 2024.07.11
유니티 프리팹 드래그 드랍  (0) 2024.05.09
AutomaticShadowDistance  (0) 2024.04.18
posted by 모카쨩
2024. 5. 9. 11:32 Unity/C#

 

 

 

 

원문링크 : 

https://forum.unity.com/threads/solved-how-to-start-draganddrop-action-so-that-sceneview-and-hierarchy-accept-it-like-with-prefabs.822531/

 

[Solved] How to start DragAndDrop action so that SceneView and Hierarchy accept it like with prefabs

Edit: Solution below. I'm building a level design tool which shows a list of prefabs in a custom editor window and lets users drag and drop these...

forum.unity.com

 

 

이 코드는 내가 만든게 아니고 위 링크에서 가져와 간소화 한것일뿐이다

 void OnEnable()
{
    SceneView.duringSceneGui += OnSceneGUI;
    EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
}

 void OnDisable()
{
    SceneView.duringSceneGui -= OnSceneGUI;
    EditorApplication.hierarchyWindowItemOnGUI -= OnHierarchyGUI;
}
 void OnSceneGUI(SceneView obj)
{
    HandleDragAndDropEvents();
}

 void OnHierarchyGUI(int instanceID, Rect selectionRect)
{
    HandleDragAndDropEvents();
}
 void HandleDragAndDropEvents()
{
    if (Event.current.type == EventType.DragUpdated)
    {
        OnDragUpdated();
    }
    if (Event.current.type == EventType.DragPerform)
    {
        OnDragPerform();
    }
}
void OnDragUpdated()
{
    Debug.Log("OnDragUpdated()");
}
void OnDragPerform()
{
    Debug.Log("OnDragPerform()");
}

 

 

 

아바타 툴 만들때 사용되었다

 

 

 

 

 

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

유니티 라이트 레졸루션 개별설정  (0) 2024.05.12
AutomaticShadowDistance  (0) 2024.04.18
c# Dictionary(딕셔너리) 관련  (0) 2024.03.19
posted by 모카쨩
2024. 4. 18. 15:40 Unity/C#

 

 

 

https://ahzkwid.booth.pm/items/5632873

 

Automatic Shadow Distance - Wmup - BOOTH

ワールド用です DirectionalLightの影の長さをFPSに応じて自動的に変更するツールです。 動きがきれいじゃないので、キャラクターシャドウ専用に使用するのをお勧めします - Code - https://gist.githu

ahzkwid.booth.pm

여기서 다운 가능

 

 

 

 

 

using UdonSharp;
using UnityEngine;
using UnityEngine.UI;
using VRC.SDKBase;
using VRC.Udon;

[UdonBehaviourSyncMode(BehaviourSyncMode.None)]
public class AutomaticShadowDistance : UdonSharpBehaviour
{
    public Light directionalLight;
    public float frameCheckTimeCycle = 3f;
    int playerLayerIndex = 9;
    public Vector2 targetFps = new Vector2(30, 60);
    public Vector2 defaultShadowDistance = new Vector2(10, 80);
    public Vector2 playerShadowDistance = new Vector2(1,15);

    float tPre = 2;

    void UpdateShadowDistance(float t)
    {
        var defaultShadowDistanceMin = defaultShadowDistance.x;
        var defaultShadowDistanceMax = defaultShadowDistance.y;
        var playerShadowDistanceMin = playerShadowDistance.x;
        var playerShadowDistanceMax = playerShadowDistance.y;


        var targetDistanceDefault = Mathf.Lerp(defaultShadowDistanceMin, defaultShadowDistanceMax, t);
        var targetDistancePlayer = Mathf.Lerp(playerShadowDistanceMin, playerShadowDistanceMax, t);
        
        {
            //QualitySettings.shadowDistance = targetDistanceDefault;
        }
        {
            var ShadowCullDistances = new float[32];
            //ShadowCullDistances[0] = Mathf.Lerp(ShadowCullDistances[0], targetDistanceDefault, 0.1f);
            ShadowCullDistances[0] = targetDistanceDefault;
            ShadowCullDistances[11] = ShadowCullDistances[0];
            ShadowCullDistances[13] = ShadowCullDistances[0];
            ShadowCullDistances[14] = ShadowCullDistances[0];
            ShadowCullDistances[playerLayerIndex] = targetDistancePlayer;
            ShadowCullDistances[10] = ShadowCullDistances[playerLayerIndex];
            ShadowCullDistances[18] = ShadowCullDistances[playerLayerIndex];
            directionalLight.layerShadowCullDistances = ShadowCullDistances;

            //Camera.main.layerCullDistances = ShadowCullDistances;
        }
    }

    LightShadows shadowType = LightShadows.Soft;
    void Start()
    {
        //if (directionalLight==null)
        //{
        //    /*
        //    var lights = FindObjectsOfType<Light>();
        //    foreach (var light in lights)
        //    {
        //        if (light.type==LightType.Directional)
        //        {
        //            directionalLight = light;
        //        }
        //    }
        //    */
        //    /*
        //    var light= FindObjectOfType<Light>();
        //    if (light.type == LightType.Directional)
        //    {
        //        directionalLight = light;
        //    }
        //    */
        //}
        if (directionalLight.shadows != LightShadows.None)
        {
            shadowType = directionalLight.shadows;
        }

        UpdateShadowDistance(0);

        lastCheckTime = 0;
    }
    float lastCheckTime = 0;
    int frameCount = 0;

    public Toggle toggle;
    public Slider slider;
    public GameObject lockPanel;

    public bool alwaysUseShdow = true;
    bool CheckT(float t)
    {
        return ((Mathf.Abs(t - tPre) > 0.1f)
            || ((t == 0) && (tPre < 0.1f))
            || ((t == 1) && (tPre > 0.9f)));
    }
    void Update()
    {
        var useShadowOff = !alwaysUseShdow;

        var toggleManual = toggle;
        lockPanel.SetActive(toggleManual.isOn == false);



        var useShadowOffvalue = 0.1f;
        if (toggleManual.isOn)
        {
            if (slider.value > useShadowOffvalue)
            {
                var t = (slider.value - useShadowOffvalue) * (1f / (1f- useShadowOffvalue));
                if (CheckT(t))
                {
                    UpdateShadowDistance(t);
                    tPre = t;
                }
                if (useShadowOff)
                {
                    if (directionalLight.shadows == LightShadows.None)
                    {
                        directionalLight.shadows = shadowType;
                    }
                }
            }
            else
            {
                if (useShadowOff)
                {
                    if (directionalLight.shadows != LightShadows.None)
                    {
                        directionalLight.shadows = LightShadows.None;
                    }
                }
            }
        }
        else
        {


            frameCount++;

            if (Time.time - lastCheckTime >= frameCheckTimeCycle)
            {
                var fps = 0f;
                if (Time.deltaTime > 0)
                {
                    fps = 1f / Time.deltaTime;
                }
                if (frameCheckTimeCycle > 0.1f)
                {
                    fps = frameCount / frameCheckTimeCycle;
                }


                var min = targetFps.x;
                var max = targetFps.y;
                var t = (Mathf.Clamp(fps, min, max) - min) / (max - min);

                /*
                if ((Mathf.Abs(t - tPre) > 0.1f)
                    || ((t == 0) && (tPre < 0.1f))
                    || ((t == 1) && (tPre > 0.9f)))
                */
                if (CheckT(t))
                {

                    UpdateShadowDistance(t);
                    tPre = t;

                }


                if (Time.time > 10)
                {
                    if (useShadowOff)
                    {
                        if (directionalLight.shadows == LightShadows.None)
                        {
                            if (t > 0.8f)
                            {
                                directionalLight.shadows = shadowType;
                            }
                        }
                        else
                        {
                            if (fps < min / 2)
                            {
                                directionalLight.shadows = LightShadows.None;
                            }
                        }
                    }
                }
                if (directionalLight.shadows == LightShadows.None)
                {
                    slider.value = 0f;
                }
                else
                {
                    slider.value = useShadowOffvalue + t * (1f- useShadowOffvalue);
                }


                frameCount = 0;
                lastCheckTime = Time.time;
            }
        }
    }
}

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

유니티 프리팹 드래그 드랍  (0) 2024.05.09
c# Dictionary(딕셔너리) 관련  (0) 2024.03.19
자주 쓰는 DateTime 코드 모음  (0) 2023.12.19
posted by 모카쨩
2024. 3. 19. 01:48 Unity/C#

 

ClassList to Dictionary

아래의 경우에는 중복되는 userCode의 경우 price를 전부 병합하여 생성한다

왜냐면 Dictionary는 동일키생성을 허용하지 않기 때문이다

 

v1

더보기
var dictionary = classList.GroupBy(x => x.userCode).ToDictionary(x=>x.First().userCode, x=>x.Sum(x=>x.price));

v2

var dictionary = groups.ToDictionary(x => x.Key, x => x.ToList());

 

 

 

Dictionary Sort

//오름차순 정렬
dictionary=dictionary.OrderBy(x => x.Value).ToDictionary(x=>x.Key, x => x.Value); //오름차순 정렬
 
//내림차순 정렬
dictionary=dictionary.OrderByDescending(x => x.Value).ToDictionary(x=>x.Key, x => x.Value); //내림차순 정렬

 

 

슬라이스

{
    //슬라이스(길이만큼 자르기)
    var length = 3;
    dictionary = dictionary.Take(length).ToDictionary(x => x.Key, x => x.Value);
}

 

 

중복제거

단 Dictionary는 원래 중복 Key를 허용하지 않기 때문에 Value만 가능하다

dictionary = dictionary.GroupBy(x => x.Value).Select(x => x.First()).ToDictionary(x => x.Key, x => x.Value); //중복제거

 

 

 

FindIndex

순위를 매길때 사용했다

var rank = dictionary.Keys.ToList().FindIndex(x => x == id);

 

 

Insert

중간에 넣기 전에 동일키를 지우고 넣는다

var item = dictionary.ElementAt(index);
dictionary.Remove(item.Key);
var list = dictionary.ToList();
list.Insert(length - 1, item);
dictionary = list.ToDictionary(x=>x.Key, x => x.Value);

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

AutomaticShadowDistance  (0) 2024.04.18
자주 쓰는 DateTime 코드 모음  (0) 2023.12.19
Path 연산  (0) 2023.09.09
posted by 모카쨩
2023. 12. 19. 14:19 Unity/C#

현재시간

long second= System.DateTime.Now.Ticks / 10000000 % 60;
long minute= System.DateTime.Now.Ticks / 10000000/60 % 60;
long hour= System.DateTime.Now.Ticks / 10000000/60/60 % 24;
System.DateTime.NowGetHour(System.DateTime.Now) //24시는 0으로 표기되고 23시는 23시로 나온다
DateTime Date = DateTime.UtcNow.AddYears(-10) //10년전


System.DateTime.Now
//결과:2021-06-08 PM 6:00:44



//Unix시간, 유닉스 타임 스탬프 (UnixTimeStamp)
//DateTime버전 길지만 변환이 쉬움
DateTime date=DateTime.Now;
(Int32)(date.Subtract(new DateTime(1970, 1, 1))).TotalSeconds
//결과: 2021-1-16 (6:12:31 GMT) => 1610788351

//역변환
DateTime date= new DateTime(1970, 1, 1).AddSeconds(unixTime);
//결과: 2021-1-16 (6:12:31 GMT) => 1610788351

//DateTimeOffset버전 짧지만 변환이 어려움
DateTimeOffset.Now.ToUnixTimeSeconds();



var time = System.DateTime.Now;
Debug.Log($"<b>[{time.Hour.ToString("D2")}:{time.Minute.ToString("D2")}:{time.Second.ToString("D2")}.{time.Millisecond.ToString("D3")}]</b>");
//굵은 글씨로 현재시간 시분초(소숫점 포함) 표기
//결과 : [18:17:30.428]

 

 

ticks를 datetime으로

long ticks = System.DateTime.UtcNow.Ticks;
System.DateTime dateTime = new System.DateTime(ticks);
Debug.Log(dateTime);

 

dateTime to int

기준일로부터 68년간 유효하다 (최대 69년)

//68년간 유효
long offsetYears = System.DateTime.MinValue.AddYears(1953).Ticks;
Debug.Log($"offsetYears: {offsetYears}");

long ticks = System.DateTime.Now.Ticks;
Debug.Log($"ticks: {ticks}");

int ticksInt = (int)((ticks- offsetYears)/ 10000000);
Debug.Log($"ticksInt: {ticksInt}");

long intToTicks = (long)ticksInt * 10000000+ offsetYears;
Debug.Log($"intToTicks: {intToTicks}");

System.DateTime dateTime = new System.DateTime(intToTicks);
Debug.Log($"dateTime: {dateTime}");

 

 

datetime 문자열 변환

var dateTimeString = dateTime.ToString();
dateTime= System.DateTime.Parse(dateTimeString);

 

 

DateTime To TimeSpan

원문 : https://stackoverflow.com/questions/17959440/convert-datetime-to-timespan

var timeSpan = System.TimeSpan.FromTicks(dateTime.Ticks);

 

 

DateTime To TotalDays

var timeSpan = System.TimeSpan.FromTicks(dateTime.Ticks);
var totalDays = timeSpan.TotalDays;

 

 

 

DateTime 덧셈


dateTime = dateTime.AddTicks(dateTime2.Ticks);

 

 

 

 

DateTime을 0~1 float로 변환

//오래될수록 1에 가까워짐

//샘플코드는 최대 한달

//7일전 = 0.2258064

//15일전 = 0.483871

//31일전 = 1

var lastUtcTime = System.DateTime.UtcNow.AddDays(-7); //7일전 접속

long min = System.DateTime.MinValue.Ticks;
long max = System.DateTime.MinValue.AddMonths(1).Ticks; //최대 1달
long normalizeTime = System.Math.Max((System.DateTime.UtcNow - lastUtcTime).Ticks, min);
normalizeTime = System.Math.Min(normalizeTime, max);

Debug.Log("마지막 접속으로부터 {(float)(((double)normalizeTime) / max)}개월 지남");

 

 

 

 

한달중 얼마나 지나갔는지 0~1float로 변환

단 day 기준임

v1

더보기
float CalculateDayRatioOfMonth(System.DateTime datetime)
{
    var datetimeAddMonths1 = datetime.AddMonths(1);
    var dayMax = datetimeAddMonths1.AddDays(-datetimeAddMonths1.Day).Day;
    return datetime.Day / dayMax;
}

v2

float GetDayRatioOfMonth(System.DateTime datetime)
{
    return datetime.Day / (float)System.DateTime.DaysInMonth(datetime.Year, datetime.Month);
}

 

 

 

날짜부분만 추출

v1

var date=System.DateTime.Parse(krTime.ToShortDateString());

 

v2

var date = krTime.Date;

 

 

DateTime의 Lerp

ChatGPT가 짜줬다


System.DateTime LerpDateTime(System.DateTime start, System.DateTime end, float t)
{
    var ticksStart = start.Ticks;
    var ticksEnd = end.Ticks;
    var ticksLerp = (long)(ticksStart + (ticksEnd - ticksStart) * (double)t);
    return new System.DateTime(ticksLerp);
}

 

 

한국시간 반환

var krTime = System.DateTime.UtcNow.AddHours(9);

 

 

 

 

 

일몰일출시간 반환

한국기준이고 2022년 기준으로 만들었다

 

 

 

 

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

c# Dictionary(딕셔너리) 관련  (0) 2024.03.19
Path 연산  (0) 2023.09.09
csv 사용법  (0) 2022.03.06
posted by 모카쨩
2023. 9. 9. 19:09 Unity/C#

 

 

 

생각보다 쓸일이 많더라

한 점에서 Path까지의 최단지점

맨 위에건 AI가 짜주었다

    Vector3 ClosestPoint(Vector3 a, Vector3 b, Vector3 position)
    {
        Vector3 ab = b - a;
        Vector3 ap = position - a;
        float t = Vector3.Dot(ap, ab) / Vector3.Dot(ab, ab);
        t = Mathf.Clamp01(t);
        return a + ab * t;
    }
    Vector3 ClosestPoint(Vector3 position, List<Vector3> path)
    {
        var closestIndex = ClosestIndex(position, path);
        var point = ClosestPoint(path[closestIndex], path[closestIndex + 1], position);

        return point;
    }
    int ClosestIndex(Vector3 position, List<Vector3> path)
    {
        float minDistance = float.MaxValue;
        int closestIndex = 0;

        for (int i = 0; i < path.Count - 1; i++)
        {
            var point = ClosestPoint(path[i], path[i + 1], position);
            var distance = Vector3.Distance(point, position);

            if (distance < minDistance)
            {
                minDistance = distance;
                closestIndex = i;
            }
        }

        return closestIndex;
    }
    float ClosestLenth(Vector3 position, List<Vector3> path)
    {
        var closestIndex = ClosestIndex(position, path);
        var closestLenth = 0f;

        for (int i = 0; i < closestIndex; i++)
        {
            closestLenth += Vector3.Distance(path[i], path[i + 1]);
        }
        if (path.Count > 1)
        {
            var closestPoint = ClosestPoint(path[closestIndex], path[closestIndex + 1], position);
            closestLenth += Vector3.Distance(path[closestIndex], closestPoint);
        }

        return closestLenth;
    }

 

 

 

총 길이

    float TotalLength(List<Vector3> path)
    {
        float totalLength = 0;
        for (int i = 0; i < path.Count - 1; i++)
        {
            totalLength += Vector3.Distance(path[i], path[i + 1]);
        }
        return totalLength;
    }

 

 

Progress 변환

위에 두개가 있어야 쓸수 있다

나중에 생각해봤는데 ProgressToPosition보다 lerp라고 쓰는게 나을듯


    float GetProgress(Vector3 a, Vector3 b, Vector3 position)
    {
        var ab = b - a;
        var ap = position - a;
        var progress = Vector3.Dot(ap, ab) / Vector3.Dot(ab, ab);
        return Mathf.Clamp01(progress);
    }
    float GetProgress(Vector3 position, List<Vector3> path)
    {
        var progress = ClosestLenth(position, path) / TotalLength(path);
        return Mathf.Clamp01(progress);
    }
    Vector3 ProgressToPosition(Vector3 a, Vector3 b,float progress)
    {
        return a+ (b - a) * Mathf.Clamp01(progress);
        //rotation = Quaternion.LookRotation(ab); //이정돈 외부에서 처리하라고
    }
    (Vector3 position, Quaternion rotation) ProgressToPosition(float progress,List<Vector3> path)
    {
        progress = Mathf.Clamp01(progress);
        float totalLength = TotalLength(path);
        float currentLength = progress * totalLength;
        float accumulatedLength = 0;

        for (int i = 0; i < path.Count - 1; i++)
        {
            float segmentLength = Vector3.Distance(path[i], path[i + 1]);
            if (accumulatedLength + segmentLength > currentLength)
            {
                float t = (currentLength - accumulatedLength) / segmentLength;
                var position = Vector3.Lerp(path[i], path[i + 1], t);
                var rotation = transform.rotation;
                if (path.Count >= 2)
                {
                    rotation = Quaternion.LookRotation(path[i + 1] - path[i]);
                }
                return (position, rotation);
            }
            accumulatedLength += segmentLength;
        }
        {
            var position = path[path.Count - 1];
            var rotation = transform.rotation;
            if (path.Count >= 2)
            {
                rotation = Quaternion.LookRotation(path[path.Count - 1] - path[path.Count - 2]);
            }
            return (position, rotation);
        }
    }

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

자주 쓰는 DateTime 코드 모음  (0) 2023.12.19
csv 사용법  (0) 2022.03.06
Windows DLL경로  (0) 2022.02.12
posted by 모카쨩

저사양 유저용 블로그 진입