각도계산
결과값이 각도일 경우에는 위 링크로
결과값이 좌표일 경우에는 이 글을 이용
LenPos
각도를 좌표로
Quaternion direction;
Vecter3 distance;
LenPos = direction * Vector3.forward * distance
유니티판 PointDirection
2D 계산용
Debug.Log(Quaternion.Euler(0, 0, 0) * Vector2.right); //(1, 0, 0)
Debug.Log(Quaternion.Euler(0, 0, 90) * Vector2.right); //(0, 1, 0)
Debug.Log(Quaternion.Euler(0, 0, 180) * Vector2.right); //(-1, 0, 0)
Debug.Log(Quaternion.Euler(0, 0, 270) * Vector2.right); //(0, -1, 0)
ScreenToRectPosition
var canvas = GetComponentInParent<Canvas>();
Camera cam = null;
switch (canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
break;
case RenderMode.ScreenSpaceCamera:
case RenderMode.WorldSpace:
cam = canvas.worldCamera;
break;
default:
break;
}
if (cam == null)
{
cam = Camera.main;
}
switch (canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
handle.transform.position = eventData.position;
break;
case RenderMode.ScreenSpaceCamera:
case RenderMode.WorldSpace:
Vector3 rectPos;
RectTransformUtility.ScreenPointToWorldPointInRectangle(GetComponent<RectTransform>(), eventData.position, cam, out rectPos);
handle.transform.position = rectPos;
break;
default:
break;
}
위에서 카메라만 가져올땐 약식으로 이거 써도 된다
public (Canvas, Camera) GetCanvasCamera()
{
var canvas = GetComponentInParent<Canvas>();
var camera = canvas.worldCamera;
if (camera == null)
{
camera = Camera.main;
}
return (canvas,camera);
}
특정 각도를 upVector삼아서 회전
(노란색 : 회전시킨 벡터)
(빨간색 : 기준각도)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VectorRotationTest : MonoBehaviour
{
void OnDrawGizmos()
{
//입력값
var axis = new Vector3(-2.85f, 1.4f, 3.4f);
var a = transform.rotation;
var b = Quaternion.Euler( 0, 0, (Time.time * 30) % 360);
//노란색원의 좌표계
var radius = Vector2.Distance(Vector2.zero, new Vector2(axis.x, axis.y));
var center = transform.position + a * Vector3.forward * axis.z;
UnityEngine.Debug.DrawLine(center, center + a * Vector3.up * radius, Color.blue);
UnityEngine.Debug.DrawLine(center, center + a * Vector3.right * radius, Color.green);
//노란색원
UnityEditor.Handles.color = Color.yellow;
UnityEditor.Handles.DrawWireDisc(center, a * Vector3.forward, radius);
UnityEditor.Handles.color = Color.white;
//흰색원과 좌표계
UnityEngine.Debug.DrawLine(transform.position, center, Color.red);
UnityEngine.Debug.DrawLine(transform.position, transform.position + a * Vector3.up, Color.blue);
UnityEngine.Debug.DrawLine(transform.position, transform.position + a * Vector3.right, Color.green);
UnityEditor.Handles.DrawWireDisc(transform.position, a * Vector3.forward, 1f);
var upRotation = a;
//핵심
UnityEngine.Debug.DrawLine(transform.position, transform.position + upRotation * b * axis, Color.yellow);
//검은색 선
UnityEngine.Debug.DrawLine(transform.position, transform.position + upRotation * b * Quaternion.Euler(0, 0, 90) * axis, Color.black);
UnityEngine.Debug.DrawLine(transform.position, transform.position + upRotation * b * Quaternion.Euler(0, 0, 180) * axis, Color.black);
UnityEngine.Debug.DrawLine(transform.position, transform.position + upRotation * b * Quaternion.Euler(0, 0, 270) * axis, Color.black);
}
}
벡터를 6방향으로 정규화
var axisNormal=vector;
if (Mathf.Abs(axisNormal.x) > Mathf.Abs(axisNormal.y))
{
axisNormal.y = 0;
}
if (Mathf.Abs(axisNormal.x) > Mathf.Abs(axisNormal.z))
{
axisNormal.z = 0;
}
else
{
axisNormal.x = 0;
}
axisNormal = axisNormal.normalized;
GPT가 짜준 패스에서 최단지점 구하는 함수
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); // a와 b 사이의 지점만을 고려하려면 이 줄을 추가합니다.
return a + ab * t;
}
Vector3 ClosestPoint(Vector3 position)
{
var path = GetPath();
float minDistance = float.MaxValue;
Vector3 closestPoint = Vector3.zero;
for (int i = 0; i < path.Count - 1; i++)
{
Vector3 point = ClosestPoint(path[i], path[i + 1], position);
float distance = Vector3.Distance(point, position);
if (distance < minDistance)
{
minDistance = distance;
closestPoint = point;
}
}
return closestPoint;
}
List<Vector3> GetPath()
{
var childs = new List<Transform>();
for (int i = 0; i < tracksParent.childCount; i++)
{
childs.Add(tracksParent.GetChild(i));
}
var path = childs.ConvertAll(x => x.position);
return path;
}
상대좌표
그러니까 글로벌 좌표를 로컬 좌표로 바꿔준다
v1
스케일값은 계산되어있지 않다
var localPosition = Quaternion.Inverse(transform.rotation) * (globalPosition - transform.position);
역변환 포함
v2
var globalPosition = transform.TransformPoint(localPosition);
var localPosition = transform.InverseTransformPoint(globalPosition);
벡터를 특정 각도로 랜덤하게 회전
FPS 게임에서 총알 각도등을 계산할때 쓴다
기존에 내가 계산하던 방식
var vector = Camera.main.transform.forward;
var angle = 5f;
var randomAngle = Random.Range(0, angle);
var rotatedVector = Quaternion.LookRotation(vector, Vector3.up) * Quaternion.Euler(0, 0, Random.Range(0f, 360f)) * Quaternion.Euler(randomAngle, 0, 0) * Vector3.forward * Vector3.Distance(Vector3.zero, vector);
Debug.DrawRay(Camera.main.transform.position, rotatedVector, Color.black);
AI가 짜준 방식
이쪽이 더 효율적이다. 위에건 사람이 작동원리를 알기 쉬우니 그냥 둠. 다른 게임엔진에서 쓸수도 있고
var vector = Camera.main.transform.forward;
var angle = 5f;
var randomAngle = Random.Range(0, angle);
var rotatedVector = Quaternion.AngleAxis(randomAngle, Random.onUnitSphere) * vector;
Debug.DrawRay(Camera.main.transform.position, rotatedVector, Color.black);
WorldPosition을 ScreenPosition으로
var cam = Camera.main;
var screenPoint = RectTransformUtility.WorldToScreenPoint(cam, worldPosition);
그리고 하기는 예제이다
https://wmmu.tistory.com/search/WorldToScreenPoint
WorldPosition, ScreenPosition, localRectPosion 종합세트
v1
#if UNITY_EDITOR
public GameObject handle;
void OnDrawGizmos()
{
// Draw a semitransparent blue cube at the transforms position
var rectTransform = GetComponent<RectTransform>();
if (rectTransform == null)
{
return;
}
var lossyScale = rectTransform.lossyScale;
float wid = rectTransform.rect.width;
float hei = rectTransform.rect.height;
var pivot = rectTransform.pivot;
Vector3 downPos = transform.up * lossyScale.y * hei * (pivot.y - 1);
Vector3 upPos = transform.up * lossyScale.y * hei * pivot.y;
Vector3 leftPos = transform.right * lossyScale.x * wid * (pivot.x - 1);
Vector3 rightPos = transform.right * lossyScale.x * wid * pivot.x;
Gizmos.color = Color.white;
//꼭지점 추출
var worldPositions = new Vector3[4];
worldPositions[0] = transform.position + upPos + leftPos;
worldPositions[1] = transform.position + upPos + rightPos;
worldPositions[2] = transform.position + downPos + leftPos;
worldPositions[3] = transform.position + downPos + rightPos;
var worldHandlePosition = handle.transform.position;
Gizmos.DrawLine(worldPositions[0], worldPositions[1]);
Gizmos.DrawLine(worldPositions[2], worldPositions[3]);
Gizmos.DrawLine(worldPositions[0], worldPositions[2]);
Gizmos.DrawLine(worldPositions[1], worldPositions[3]);
//worldPosition 2 screenPosition
Vector2[] screenPositions;
Vector2 screenHandlePosition;
{
var canvas = GetComponentInParent<Canvas>();
Camera cam = null;
switch (canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
break;
case RenderMode.ScreenSpaceCamera:
case RenderMode.WorldSpace:
cam = canvas.worldCamera;
break;
default:
break;
}
if (cam == null)
{
cam = Camera.main;
}
screenPositions = System.Array.ConvertAll(worldPositions, wp => RectTransformUtility.WorldToScreenPoint(cam, wp));
screenHandlePosition = RectTransformUtility.WorldToScreenPoint(cam, worldHandlePosition);
for (int i = 0; i < 4; i++)
{
var color = Color.white;
if (i < 2)
{
color = Color.black;
}
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldPositions[i], $"wp[{i}] : {worldPositions[i].ToString("F2")}\nsp[{i}] : {screenPositions[i]}", guiStyle);
}
}
//worldPosition 2 normalizedPosionLocal
Vector2 localRectHandlePosion;
{
var l = (Quaternion.Inverse(transform.rotation) * (transform.position + leftPos)).x;
var r = (Quaternion.Inverse(transform.rotation) * (transform.position + rightPos)).x;
var t = (Quaternion.Inverse(transform.rotation) * (transform.position + upPos)).y;
var d = (Quaternion.Inverse(transform.rotation) * (transform.position + downPos)).y;
localRectHandlePosion = Quaternion.Inverse(transform.rotation) * worldHandlePosition;
localRectHandlePosion.x = (localRectHandlePosion.x - l) / (r - l);
localRectHandlePosion.y = (localRectHandlePosion.y - d) / (t - d);
{
var color = Color.green;
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldHandlePosition, $"whp : {worldHandlePosition.ToString("F2")}\nshp : {screenHandlePosition}\nlrhp : {localRectHandlePosion.ToString("F2")}", guiStyle);
}
}
//localRectHandlePosion 2 worldPosition
{
var l = (Quaternion.Inverse(transform.rotation) * (transform.position + leftPos)).x;
var r = (Quaternion.Inverse(transform.rotation) * (transform.position + rightPos)).x;
var t = (Quaternion.Inverse(transform.rotation) * (transform.position + upPos)).y;
var d = (Quaternion.Inverse(transform.rotation) * (transform.position + downPos)).y;
var worldPos = transform.rotation * new Vector3(l + localRectHandlePosion.x * (r - l), d + localRectHandlePosion.y * (t - d), 0);
{
var color = Color.gray;
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldPos, "\n\n\nworldPos", guiStyle);
}
}
}
#endif
v2
#if UNITY_EDITOR
public GameObject handle;
void OnDrawGizmos()
{
// Draw a semitransparent blue cube at the transforms position
var rectTransform = GetComponent<RectTransform>();
if (rectTransform == null)
{
return;
}
var lossyScale = rectTransform.lossyScale;
float wid = rectTransform.rect.width;
float hei = rectTransform.rect.height;
var pivot = rectTransform.pivot;
Vector3 downPos = transform.up * lossyScale.y * hei * (pivot.y - 1);
Vector3 upPos = transform.up * lossyScale.y * hei * pivot.y;
Vector3 leftPos = transform.right * lossyScale.x * wid * (pivot.x - 1);
Vector3 rightPos = transform.right * lossyScale.x * wid * pivot.x;
Gizmos.color = Color.white;
//꼭지점 추출
var worldPositions = new Vector3[4];
worldPositions[0] = transform.position + upPos + leftPos;
worldPositions[1] = transform.position + upPos + rightPos;
worldPositions[2] = transform.position + downPos + leftPos;
worldPositions[3] = transform.position + downPos + rightPos;
var worldHandlePosition= handle.transform.position;
Gizmos.DrawLine(worldPositions[0], worldPositions[1]);
Gizmos.DrawLine(worldPositions[2], worldPositions[3]);
Gizmos.DrawLine(worldPositions[0], worldPositions[2]);
Gizmos.DrawLine(worldPositions[1], worldPositions[3]);
//worldPosition 2 screenPosition
Vector2[] screenPositions;
Vector2 screenHandlePosition;
{
var canvas = GetComponentInParent<Canvas>();
Camera cam = null;
switch (canvas.renderMode)
{
case RenderMode.ScreenSpaceOverlay:
break;
case RenderMode.ScreenSpaceCamera:
case RenderMode.WorldSpace:
cam = canvas.worldCamera;
break;
default:
break;
}
if (cam == null)
{
cam = Camera.main;
}
screenPositions = System.Array.ConvertAll(worldPositions, wp => RectTransformUtility.WorldToScreenPoint(cam, wp));
screenHandlePosition = RectTransformUtility.WorldToScreenPoint(cam, worldHandlePosition);
for (int i = 0; i < 4; i++)
{
var color = Color.white;
if (i < 2)
{
color = Color.black;
}
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldPositions[i], $"wp[{i}] : {worldPositions[i].ToString("F2")}\nsp[{i}] : {screenPositions[i]}", guiStyle);
}
}
//worldPosition 2 normalizedPosionLocal
Vector2 normalizedPositionLocal;
{
Vector2 localHandlePoint = rectTransform.InverseTransformPoint(worldHandlePosition);
normalizedPositionLocal = (localHandlePoint- rectTransform.rect.min)/ rectTransform.rect.size;
{
var color = Color.green;
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldHandlePosition, $"whp : {worldHandlePosition.ToString("F2")}\nshp : {screenHandlePosition}\nlhp : {normalizedPositionLocal.ToString("F2")}", guiStyle);
}
}
//normalizedPosionLocal 2 worldPosition
{
var rect = rectTransform.rect;
var worldPos = transform.TransformPoint(rect.min + normalizedPositionLocal * rect.size);
{
var color = Color.gray;
var guiStyle = new GUIStyle();
guiStyle.fontSize = 16;
guiStyle.normal.textColor = color;
UnityEditor.Handles.Label(worldPos, "\n\n\nworldPos", guiStyle);
}
}
}
#endif
씬뷰상 오브젝트 거리
아바타툴 만들때 사용함
var screenPoint = HandleUtility.WorldToGUIPoint( transform.position);
targets = targets.OrderBy(target => Vector2.Distance(HandleUtility.WorldToGUIPoint(target.transform.position), screenPoint)).ToArray();
'Unity > C#' 카테고리의 다른 글
유니티 빌드 관련 코드 (0) | 2021.08.09 |
---|---|
유니티 커스텀 인터페이스 (0) | 2021.06.24 |
유니티 기즈모 (Gizmo) 관련코드 (0) | 2021.06.15 |