UnityのuGUIで点と点を結ぶ線分を作成する
Canvas - Overlay 限定で点と点の線分を書く3D上のワールドの点とCanvas上の点に線分を表示したかったのでコンポーネントを作成しました。
画像のような線分を表示できるようになります。
コード
UILineコンポーネントは、以下の条件下で機能します。
- UIのCanvasの設定がOverlayであること
- 3Dのワールド座標 Transform.position と RectTransform.localPositionの対であること
- UILineのプロパティlineImageのwidthを小さくすると細い線を描画します。
using UnityEngine;
using UnityEngine.UI;
// only Canvas - Overlay
public class UILine : MonoBehaviour
{
[SerializeField] private RectTransform canvasRectTransform;
[SerializeField] private Image lineImage;
public void Draw(Transform trans3D, RectTransform uiElement)
{
if (trans3D == null || uiElement == null)
{
return;
}
Draw(trans3D.position, uiElement.localPosition)
}
public void Draw(Vector3 worldPosition, Vector2 uiElementLocalPos)
{
var mainCamera = Camera.main;
if (lineImage == null || canvasRectTransform == null || mainCamera == null)
{
return;
}
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(mainCamera, worldPosition);
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTransform, screenPoint, null, out Vector2 localPoint3D);
DrawLineBetweenPoints(localPoint3D, uiElementLocalPos);
}
public void DrawLineBetweenPoints(Vector2 localPositionA, Vector2 localPositionB)
{
Vector2 direction = (localPositionA - localPositionB).normalized;
float distance = Vector2.Distance(localPositionA, localPositionB);
lineImage.rectTransform.sizeDelta = new Vector2(distance, lineImage.rectTransform.sizeDelta.y);
lineImage.rectTransform.pivot = new Vector2(0.5f, 0.5f);
lineImage.rectTransform.anchoredPosition = (localPositionA + localPositionB) / 2;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
lineImage.rectTransform.localEulerAngles = new Vector3(0, 0, angle);
}
}