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 |