거리 측정 Linerenderer 사용으로 변경

This commit is contained in:
jmaniuvc
2025-04-03 18:24:58 +09:00
parent 7f98e1a06c
commit 7005d76198
9 changed files with 376 additions and 46 deletions

View File

@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
namespace XED
{
//TODO::areabox가 아니라 TwinObject를 대상으로 동작하도록 수정
public class ObjectDistanceLine : MonoBehaviour
{
private Vector3 centerPoint = new();
private Vector3[] edges = new Vector3[4];
private LineRenderer[] lineRenderers = new LineRenderer[4];
private int[] distances = new int[4];
private Vector3[] hits = new Vector3[4];
[SerializeField]
private float thickness;
private int rot;
private Dictionary<Vector3, Vector3> dirTable = new();
TwinObject target;
HashSet<TwinObject> targets = new();
public event Action onTargetEvent;
public event Action onTargetMissing;
public event Action<Vector3, int, int> onLineUpdate;
public override void AfterAwake()
{
//var labelCanvas;
var lineMat = Resources.Load<Material>("Materials/Mat_LineRender");
for (int i = 0; i < lineRenderers.Length; i++)
{
lineRenderers[i] = new GameObject("DistanceLine").AddComponent<LineRenderer>();
lineRenderers[i].transform.SetParent(transform, true);
lineRenderers[i].material = lineMat;
lineRenderers[i].positionCount = 2;
lineRenderers[i].startWidth = thickness;
lineRenderers[i].endWidth = thickness;
}
//onTargetEvent += ()=>labelCanvas.panel_objectdistancelabellist.SetActive(true);
//onTargetMissing += ()=>labelCanvas.panel_objectdistancelabellist.SetActive(false);
//onLineUpdate += labelCanvas.panel_objectdistancelabellist.DistanceLabelsSetting;
}
public void SetTarget(TwinObject target)
{
if (target is Wall || target is WallGroup)
return;
this.target = target;
targets.Add(target);
gameObject.SetActive(true);
onTargetEvent?.Invoke();
}
private void EdgePoints()
{
var size = target.physics.areabox.bounds.size;
edges[0] = centerPoint + EdgePointCalculate(-size.x, -size.z, centerPoint);
edges[1] = centerPoint + EdgePointCalculate(size.x, -size.z, centerPoint);
edges[2] = centerPoint + EdgePointCalculate(size.x, size.z, centerPoint);
edges[3] = centerPoint + EdgePointCalculate(-size.x, size.z, centerPoint);
}
private void CenterPoints()
{
var size = target.physics.areabox.bounds.size;
edges[0] = centerPoint + EdgePointCalculate(-size.x, 0f, centerPoint);
edges[1] = centerPoint + EdgePointCalculate(size.x, 0f, centerPoint);
edges[2] = centerPoint + EdgePointCalculate(0f, -size.z, centerPoint);
edges[3] = centerPoint + EdgePointCalculate(0f, size.z, centerPoint);
}
private Vector3 EdgePointCalculate(float xValue, float zValue, Vector3 center)
{
//대각선의 길이,
//중점길이
var point = center + (new Vector3(xValue, 0, zValue) * 0.5f);
var length = Vector3.Distance(point, center);
var dir = (point - center).normalized * length;
//var pos = RotateVector3(dir, rot);
var pos = Quaternion.AngleAxis(rot, Vector3.up) * dir;
return pos;
}
public void Off()
{
targets.Clear();
onTargetMissing?.Invoke();
}
void LineRenderSetActive(bool isActive)
{
foreach(var line in lineRenderers)
{
line.enabled = isActive;
}
}
private void Update()
{
if (target == null || targets.Count >1)
{
Off();
LineRenderSetActive(false);
return;
}
//if (areabox == null)
// return;
//Distance가 4개 모두 0이면 return?
LineRenderSetActive(true);
rot = Mathf.RoundToInt(target.physics.areabox.transform.localEulerAngles.y);
centerPoint = new Vector3(target.physics.areabox.bounds.center.x, 0, target.physics.areabox.bounds.center.z);
var angle = rot % 90f;
if (Mathf.Approximately(angle, 0f))
CenterPoints();
else
EdgePoints();
var xOrder = edges.OrderBy(l => l.x);
var zOrder = edges.OrderBy(l => l.z);
dirTable.Clear();
dirTable.TryAdd(xOrder.ElementAt(0), Vector3.left);
dirTable.TryAdd(xOrder.ElementAt(3), Vector3.right);
dirTable.TryAdd(zOrder.ElementAt(0), Vector3.back);
dirTable.TryAdd(zOrder.ElementAt(3), Vector3.forward);
for (int i = 0; i < edges.Length; i++)
{
//var dir = Dir(dirTable[edges[i]]);
var dir = dirTable[edges[i]];
if (Physics.Raycast(edges[i], dir, out RaycastHit hit, Mathf.Infinity))
{
hits[i] = hit.point;
}
else
{
hits[i] = edges[i];
}
distances[i] = Mathf.RoundToInt(Vector3.Distance(hits[i], edges[i]) * 1000f);
lineRenderers[i].SetPosition(0, edges[i]);
lineRenderers[i].SetPosition(1, hits[i]);
//3방향중 점중 가장 짧은거
var pos = DistanceTextPos(edges[i], hits[i]);
if (Mathf.Abs(pos.y) == Mathf.Infinity || float.IsNaN(pos.y))
continue;
onLineUpdate?.Invoke(pos, i, distances[i]);
}
}
private Vector3 DistanceTextPos(Vector3 edge, Vector3 hit)
{
var x = Screen.width;
var y = Screen.height;
var hitpoint = Camera.main.WorldToScreenPoint(hit);
var edgePoint = Camera.main.WorldToScreenPoint(edge);
//카메라 끝점 edge와 hit 사이;
//기울기 가져온다
var m = (hitpoint.y - edgePoint.y) / (hitpoint.x - edgePoint.x);
if (hitpoint.y > y)
{
var yPos = y;
var xPos = ((yPos - edgePoint.y) / m) + edgePoint.x;
hitpoint = new Vector3(xPos, yPos);
}
else if (hitpoint.y < 0)
{
var yPos = 0;
var xPos = ((yPos - edgePoint.y) / m) + edgePoint.x;
hitpoint = new Vector3(xPos, yPos);
}
if (hitpoint.x > x)
{
var xPos = x;
var yPos = (m * (xPos - edgePoint.x)) + edgePoint.y;
hitpoint = new Vector3(xPos, yPos);
}
else if (hitpoint.x < 0)
{
var xPos = 0;
var yPos = (m * (xPos - edgePoint.x)) + edgePoint.y;
hitpoint = new Vector3(xPos, yPos);
}
var center = (hitpoint + edgePoint) * 0.5f;
return center;
}
void Gizmo()
{
#if UNITY_EDITOR
// for (int i = 0; i < edges.Length; ++i)
// {
// Gizmos.DrawSphere(edges[i].pos, 0.1f);
// }
// for (int i = 0; i < hits.Length; ++i)
// {
// var dir = Dir(dirTable[edges[i]]);
// Handles.color = Color.yellow;
// Handles.DrawLine(edges[i].pos, hits[i], 1);
// Gizmos.DrawRay(edges[i].pos, dir * 10f);
// }
#endif
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bfac6b2ea97a0274787f0bf0d086a76d

View File

@@ -211,6 +211,7 @@ GameObject:
- component: {fileID: 7194822588214921878}
- component: {fileID: 3097470657670304171}
- component: {fileID: 5078274965939298063}
- component: {fileID: 7525121242705956087}
m_Layer: 0
m_Name: Distance_right
m_TagString: Untagged
@@ -276,6 +277,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &7525121242705956087
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1824088583583508963}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &2075515304005455769
GameObject:
m_ObjectHideFlags: 0
@@ -695,6 +708,7 @@ GameObject:
- component: {fileID: 1400843724585282578}
- component: {fileID: 2061718949882192120}
- component: {fileID: 4022013656138835912}
- component: {fileID: 4248166134889511194}
m_Layer: 0
m_Name: Distance_left
m_TagString: Untagged
@@ -760,6 +774,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &4248166134889511194
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5461546370723553429}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &7125163854521808529
GameObject:
m_ObjectHideFlags: 0
@@ -771,6 +797,7 @@ GameObject:
- component: {fileID: 6571488781575170805}
- component: {fileID: 2889234264731888109}
- component: {fileID: 5311912601517734047}
- component: {fileID: 9121733989934958637}
m_Layer: 0
m_Name: Distance_back
m_TagString: Untagged
@@ -836,6 +863,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &9121733989934958637
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7125163854521808529}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &7135956063028507155
GameObject:
m_ObjectHideFlags: 0
@@ -847,6 +886,7 @@ GameObject:
- component: {fileID: 18596219730868912}
- component: {fileID: 7819340452723330143}
- component: {fileID: 2211566357908769342}
- component: {fileID: 2122022514441583782}
m_Layer: 0
m_Name: Distance_foward
m_TagString: Untagged
@@ -912,6 +952,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &2122022514441583782
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7135956063028507155}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &7452555945768904036
GameObject:
m_ObjectHideFlags: 0
@@ -1195,6 +1247,7 @@ GameObject:
- component: {fileID: 8107414850933273690}
- component: {fileID: 9125045971131934483}
- component: {fileID: 4508713210993668394}
- component: {fileID: 553392137018333697}
m_Layer: 0
m_Name: Distance_up
m_TagString: Untagged
@@ -1260,6 +1313,18 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &553392137018333697
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8057416366647402832}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &8838398484417968805
GameObject:
m_ObjectHideFlags: 0
@@ -1271,6 +1336,7 @@ GameObject:
- component: {fileID: 6902250168712616153}
- component: {fileID: 5227252712573134147}
- component: {fileID: 1079209328243914300}
- component: {fileID: 4065362264821389741}
m_Layer: 0
m_Name: Distance_down
m_TagString: Untagged
@@ -1336,3 +1402,15 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &4065362264821389741
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8838398484417968805}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 39f918e32db5c5042be45d171306ad14, type: 3}
m_Name:
m_EditorClassIdentifier:

View File

@@ -48,7 +48,7 @@ namespace XED.Asset
assetDataHandler = new CustomAssetDataHandler(this);
assetEventHandler = new CustomAssetEventHandler(this);
projectManager = FindSingle<ProjectManager>();
interferedObjectManager = FindSingle<InterferedObjectManager>();
}
void Start()
{
@@ -56,6 +56,7 @@ namespace XED.Asset
assetScrollView = FindSingle<Canvas_Popup>().panel_assetlibrary.scrollView;
componentScrollView = FindSingle<Canvas_Popup>().panel_hierarchy.scrollView;
InterworkingDataScrollView = FindSingle<Canvas_Popup>().panel_interworkingdatalist.scrollView;
interferedObjectManager = FindSingle<InterferedObjectManager>();
renderObjectPrefab = Resources.Load<GameObject>("Prefabs/PRF_RenderObject");
assetScrollRect.onDragBegin.AddListener(OnAssetSelected);

View File

@@ -23,8 +23,6 @@ namespace XED.UI
{
Button_Object1.onClick.AddListener(() => OnButtonClick(interferedTwinObject1));
Button_Object2.onClick.AddListener(() => OnButtonClick(interferedTwinObject2));
OnClickButton += FindSingle<CameraManager>().MoveToTwinObjectPos;
}
public void Initialize(TwinObject obj1, TwinObject obj2)

View File

@@ -0,0 +1,36 @@
using UnityEngine;
using TMPro;
using XRLib.UI;
namespace XED
{
public class UI_ObjectDistance : UIBase
{
TextMeshProUGUI m_text;
private void Awake()
{
m_text = GetComponentInChildren<TextMeshProUGUI>();
}
public void SetText(float distance)
{
m_text.text = distance.ToString("F2");
}
public void SetPos(Vector3 movePoint)
{
Vector3 screenPoint = Camera.main.WorldToScreenPoint(movePoint);
transform.position = screenPoint;
if (screenPoint.z > 0)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 39f918e32db5c5042be45d171306ad14

View File

@@ -15,18 +15,23 @@ namespace XED.UI
Dictionary<(TwinObject, TwinObject), UI_InterferedObjectButton> createdButtons = new();
CameraManager cameraManager;
public override void AfterAwake()
{
Button_Close.onClick.AddListener(OnClickClose);
content = GetComponentInChildren<ScrollRect>().content;
buttonPrefab = Resources.Load<GameObject>("Prefabs/UI/PRF_InterferedObjectButton");
cameraManager = FindSingle<CameraManager>();
}
public void CreateContentButton((TwinObject, TwinObject) pair)
{
var newButton = Instantiate(buttonPrefab, content).GetComponent<UI_InterferedObjectButton>();
createdButtons.Add(pair, newButton);
newButton.OnClickButton += cameraManager.MoveToTwinObjectPos;
newButton.Initialize(pair.Item1, pair.Item2);
createdButtons.Add(pair, newButton);
}
public void RemoveContentButton((TwinObject, TwinObject) pair)

View File

@@ -10,16 +10,10 @@ namespace XED.UI
{
public class Panel_ObjectDistance : PanelBase, ISingle
{
GameObject linePrefab;
UI_ObjectDistance[] ui_ObjectDistances;
LineRenderer[] lineRenderers = new LineRenderer[6];
Dictionary<UI_ObjectDistance, LineRenderer> distanceLines = new();
RectTransform Distance_up;
RectTransform Distance_down;
RectTransform Distance_left;
RectTransform Distance_right;
RectTransform Distance_foward;
RectTransform Distance_back;
Dictionary<RectTransform, GameObject> distanceLines = new();
[SerializeField]
float lineThickness = 1;
@@ -27,14 +21,21 @@ namespace XED.UI
public override void AfterAwake()
{
linePrefab = Resources.Load<GameObject>("Prefabs/PRF_ObjectDistanceLine");
ui_ObjectDistances = GetComponentsInChildren<UI_ObjectDistance>(true);
distanceLines.Add(Distance_up, Instantiate(linePrefab));
distanceLines.Add(Distance_down, Instantiate(linePrefab));
distanceLines.Add(Distance_left, Instantiate(linePrefab));
distanceLines.Add(Distance_right, Instantiate(linePrefab));
distanceLines.Add(Distance_foward, Instantiate(linePrefab));
distanceLines.Add(Distance_back, Instantiate(linePrefab));
var lineMat = Resources.Load<Material>("Materials/Mat_LineRender");
for (int i = 0; i < lineRenderers.Length; i++)
{
lineRenderers[i] = new GameObject("DistanceLine").AddComponent<LineRenderer>();
lineRenderers[i].transform.SetParent(transform, true);
lineRenderers[i].material = lineMat;
lineRenderers[i].positionCount = 2;
lineRenderers[i].startWidth = lineThickness;
lineRenderers[i].endWidth = lineThickness;
distanceLines.Add(ui_ObjectDistances[i], lineRenderers[i]);
}
DeactivateAll();
}
@@ -48,12 +49,12 @@ namespace XED.UI
return;
}
UpdateDistance(Distance_up, Vector3.up);
UpdateDistance(Distance_down, Vector3.down);
UpdateDistance(Distance_left, Vector3.left);
UpdateDistance(Distance_right, Vector3.right);
UpdateDistance(Distance_foward, Vector3.forward);
UpdateDistance(Distance_back, Vector3.back);
UpdateDistance(ui_ObjectDistances[0], Vector3.up);
UpdateDistance(ui_ObjectDistances[1], Vector3.down);
UpdateDistance(ui_ObjectDistances[2], Vector3.left);
UpdateDistance(ui_ObjectDistances[3], Vector3.right);
UpdateDistance(ui_ObjectDistances[4], Vector3.forward);
UpdateDistance(ui_ObjectDistances[5], Vector3.back);
}
public void SelectObjectFromCreate(CustomAssetRenderObject obj)
@@ -74,42 +75,35 @@ namespace XED.UI
void DeactivateAll()
{
foreach (var rect in distanceLines.Keys)
foreach (var distanceUI in distanceLines.Keys)
{
rect.gameObject.SetActive(false);
distanceLines[rect].gameObject.SetActive(false);
distanceUI.gameObject.SetActive(false);
distanceLines[distanceUI].enabled = false;
}
}
void UpdateDistance(RectTransform rect, Vector3 direction)
void UpdateDistance(UI_ObjectDistance distanceUI, Vector3 direction)
{
RaycastHit hit = selectedObject.GetObjectHit(direction);
if (hit.collider != null)
{
float distance = hit.distance;
rect.GetComponentInChildren<TextMeshProUGUI>().text = distance.ToString("F2");
Vector3 hitPoint = hit.point;
Vector3 distanceCenterPoint = hitPoint - (direction * distance / 2);
Vector3 screenPoint = Camera.main.WorldToScreenPoint(distanceCenterPoint);
rect.transform.position = screenPoint;
if (screenPoint.z > 0)
{
rect.gameObject.SetActive(true);
}
else
{
rect.gameObject.SetActive(false);
}
SetLineLength(distanceLines[rect], distanceCenterPoint, direction, distance);
distanceLines[rect].SetActive(true);
distanceUI.SetText(distance);
distanceUI.SetPos(distanceCenterPoint);
//SetLineLength(distanceLines[distanceUI], distanceCenterPoint, direction, distance);
distanceLines[distanceUI].SetPosition(0, hitPoint);
distanceLines[distanceUI].SetPosition(1, hitPoint - (direction * distance));
distanceLines[distanceUI].enabled = true;
}
else
{
rect.gameObject.SetActive(false);
distanceLines[rect].SetActive(false);
distanceUI.gameObject.SetActive(false);
distanceLines[distanceUI].enabled = false;
return;
}
}