1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using UnityEngine.UI;
5
6 public class CArrowLockAt : MonoBehaviour
7 {
8 public Transform target; //目标
9 public Transform self; //自己
10 public Image RoundScope;//指定为圆
11 public float direction; //箭头旋转的方向,或者说角度,只有正的值
12 public Vector3 u; //叉乘结果,用于判断上述角度是正是负
13
14 float devValue =100f; //离屏边缘距离
15
16
17 Quaternion originRot; //箭头原角度
18
19 // 初始化
20 void Start()
21 {
22 originRot = transform.rotation;
23 }
24
25 void Update()
26 {
27
28
29 // 计算向量和角度
30 Vector3 forVec = self.forward; //计算本物体的前向量
31 Vector3 angVec = (target.position - self.position).normalized; //本物体和目标物体之间的单位向量
32
33 #region 求指向
34 Vector3 targetVec = Vector3.ProjectOnPlane(angVec - forVec, forVec).normalized; //这步很重要,将上述两个向量计算出一个代表方向的向量后投射到本身的xy平面
35 Vector3 originVec = self.up;
36
37 direction = Vector3.Dot(originVec, targetVec); //再跟y轴正方向做点积和叉积,就求出了箭头需要旋转的角度和角度的正负
38
39 u = Vector3.Cross(originVec, targetVec);
40
41 direction = Mathf.Acos(direction) * Mathf.Rad2Deg; //转换为角度
42
43 u = self.InverseTransformDirection(u); //叉积结果转换为本物体坐标
44
45 // 给与旋转值
46 transform.rotation = originRot * Quaternion.Euler(new Vector3(0f, 0f, direction * (u.z > 0 ? 1 : -1)));
47 #endregion
48
49
50 // 计算当前物体在屏幕上的位置
51 Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(Camera.main,target.position);
52 #region 求在圆边位置
53 //圆半径
54 float range = (RoundScope.rectTransform.sizeDelta.y / 2) - 30;
55 //目标位置
56 Vector3 cc = RoundScope.transform.position + Vector3.ProjectOnPlane((target.position - self.position) - self.forward, self.forward) * range;
57 #endregion
58 // 不在屏幕内的情况
59 if (screenPos.x < devValue || screenPos.x > Screen.width - devValue || screenPos.y < devValue || screenPos.y > Screen.height - devValue || Vector3.Dot(forVec, angVec) < 0)
60 {
61 if (range < Vector3.Distance(cc, RoundScope.rectTransform.position))
62 {
63 transform.position = (cc - RoundScope.transform.position).normalized * range + RoundScope.transform.position;
64 }
65 else
66 {
67 transform.position = cc;
68 }
69 }
70 else // 在屏幕内的情况
71 {
72 transform.Rotate(0, 90, -45);
73 }
74 }
75 }