只需要一個腳本,就可以例圖的效果
廢話不多說,直接上腳本(此腳本只支持單個箭頭追蹤,如果需要實現多箭頭追蹤的效果,請自己酌情修改腳本,或者多調用幾次這個方法)
using System.Collections;
using UnityEngine;
public class UIGuidManager : MonoBehaviour
{
public Transform arrows; //2d的箭頭拖在這裏
Transform target;
Vector3 prePos = Vector3.zero;
//這個是檢測間隔,和性能掛鉤,默認爲0.2,自己可以隨更改
public float checkTime = 0.2f;
//被指向的3D對象傳入這裏,在全局的任何地方,調用一次這個方法即可
public void SetGuid(Transform _target)
{
target = _target;
}
void Start()
{
arrows.gameObject.SetActive(false);
StartCoroutine(TrakerGuider());
}
private IEnumerator TrakerGuider()
{
while (true)
{
yield return new WaitForSeconds(checkTime);
SetGuid();
}
}
private void SetGuid()
{
if (target)
{
var pos = Camera.main.WorldToScreenPoint(target.transform.position);
Debug.Log("pos:" + pos);
var distance = Vector3.Distance(prePos, pos);
if (distance < 1) { Debug.Log("沒動"); return; };
prePos = pos;
if (0 < pos.x && pos.x < Screen.width && pos.y > 0 && pos.y < Screen.height && pos.z > 0)
{
arrows.gameObject.SetActive(false);
return;
}
else
arrows.gameObject.SetActive(true);
if (pos.z < 0)
pos = pos * -1;
var startpos = new Vector3(Screen.width / 2f, Screen.height / 2f, 0);
var dir = pos - startpos;
//通過反餘弦函數獲取 向量 a、b 夾角(默認爲 弧度)
float radians = Mathf.Atan2(dir.y, dir.x);
//將弧度轉換爲 角度
float angle = radians * Mathf.Rad2Deg;
Debug.Log("angle:" + angle);
arrows.localEulerAngles = new Vector3(0, 0, angle);
// arrows.transform.LookAt(new Vector3(pos.x, pos.y, 0));
float sereenangle = (float)Screen.height / (float)Screen.width;
var va = System.Math.Abs(dir.y / dir.x);
if (va <= sereenangle)
{
var length = arrows.GetComponent<RectTransform>().sizeDelta.x;
if (pos.x < 0)
arrows.transform.position = GetNode(pos, startpos, length * 0.5f);
else
arrows.transform.position = GetNode(pos, startpos, Screen.width - length * 0.5f);
}
else
{
var length = arrows.GetComponent<RectTransform>().sizeDelta.x;
if (pos.y < 0)
arrows.transform.position = GetNode2(pos, startpos, length * 0.5f);
else
arrows.transform.position = GetNode2(pos, startpos, Screen.height - length * 0.5f);
}
}
}
private Vector3 GetNode2(Vector3 pos, Vector3 startpos, float v)
{
pos = new Vector3(pos.x, pos.y, 0);
Vector3 ab = pos - startpos;
Vector3 am = ab * (Mathf.Abs(startpos.y - v) / Mathf.Abs(pos.y - startpos.y));
Vector3 om = startpos + am;
return om;
}
private Vector3 GetNode(Vector3 pos, Vector3 startpos, float v)
{
//float high = ((startpos.x - length) * (pos.y - startpos.y) / (startpos.x - pos.x)) + startpos.y;
//return new Vector3(length, high, 0);
pos = new Vector3(pos.x, pos.y, 0);
Vector3 ab = pos - startpos;
Vector3 am = ab * (Mathf.Abs(startpos.x - v) / Mathf.Abs(pos.x - startpos.x));
Vector3 om = startpos + am;
return om;
}
}