两种屏幕HUD区域限制的做法(矩形,弧形)
HUD区域限制算是比较常用到的功能,方形的HUD区域限制多见于小地图,弧形或者椭圆多见于屏幕范围约束。
我没有研究倒角矩形做法,而是将椭圆和矩形进行插值得到一个弧度比较高的形状:
当插值为0时限制范围是椭圆,插值为1限制范围是矩形
矩形的判断使用了线段相交函数,函数来自网络收集
线段相交: http://www.cnblogs.com/hont/p/6106043.html
代码如下
using UnityEngine; using System; using System.Collections; public class HUDTest2 : MonoBehaviour { [Serializable] public class EllipseSetting { public float radius = 2f; public Vector2 scale = new Vector2(1, 1); } public Transform[] hudObjectArray; public EllipseSetting ellipseSetting = new EllipseSetting(); [Range(0, 1)] public float lerp; void OnGUI() { for (int i = 0; i < hudObjectArray.Length; i++) { var item = hudObjectArray[i]; var screenPosition = Camera.main.WorldToScreenPoint(item.transform.position); screenPosition.z = 0; screenPosition.y = Screen.height - screenPosition.y; screenPosition = HUDFix(screenPosition); GUI.Box(new Rect(screenPosition, Vector3.one * 15), ""); } } Vector3 HUDFix(Vector3 position) { var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f; var ellipsePoint = GetEllipsePoint(position); var quadPoint = GetRectPoint(position); var finalPoint = Vector3.Lerp(ellipsePoint, quadPoint, lerp); if (Vector3.Distance(center, finalPoint) >= Vector3.Distance(center, position)) return position; else return finalPoint; } Vector3 GetEllipsePoint(Vector3 currentPoint) { var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f; var current = center + (currentPoint - center).normalized * ellipseSetting.radius; current.x *= ellipseSetting.scale.x; current.y *= ellipseSetting.scale.y; return current; } Vector3 GetRectPoint(Vector3 currentPoint) { var center = new Vector3(Screen.width, Screen.height, 0) * 0.5f; const float INNER = 25; const float RAY = 10000 * 10; var p0 = new Vector3(INNER, INNER, 0); var p1 = new Vector3(Screen.width - INNER, INNER, 0); var p2 = new Vector3(INNER, Screen.height - INNER, 0); var p3 = new Vector3(Screen.width - INNER, Screen.height - INNER, 0); var dir = (currentPoint - center).normalized * RAY; var contractPoint = default(Vector3); var r = GetIntersection(p0, p1, center, center + dir, out contractPoint); if (r == 1) return contractPoint; r = GetIntersection(p1, p3, center, center + dir, out contractPoint); if (r == 1) return contractPoint; r = GetIntersection(p0, p2, center, center + dir, out contractPoint); if (r == 1) return contractPoint; GetIntersection(p2, p3, center, center + dir, out contractPoint); return contractPoint; } int GetIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 contractPoint) { contractPoint = new Vector3(0, 0); if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) + Mathf.Abs(d.y - c.y) + Mathf.Abs(d.x - c.x) == 0) { if ((c.x - a.x) + (c.y - a.y) == 0) { //Debug.Log("ABCD是同一个点!"); } else { //Debug.Log("AB是一个点,CD是一个点,且AC不同!"); } return 0; } if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) == 0) { if ((a.x - d.x) * (c.y - d.y) - (a.y - d.y) * (c.x - d.x) == 0) { //Debug.Log("A、B是一个点,且在CD线段上!"); } else { //Debug.Log("A、B是一个点,且不在CD线段上!"); } return 0; } if (Mathf.Abs(d.y - c.y) + Mathf.Abs(d.x - c.x) == 0) { if ((d.x - b.x) * (a.y - b.y) - (d.y - b.y) * (a.x - b.x) == 0) { //Debug.Log("C、D是一个点,且在AB线段上!"); } else { //Debug.Log("C、D是一个点,且不在AB线段上!"); } return 0; } if ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y) == 0) { //Debug.Log("线段平行,无交点!"); return 0; } contractPoint.x = ((b.x - a.x) * (c.x - d.x) * (c.y - a.y) - c.x * (b.x - a.x) * (c.y - d.y) + a.x * (b.y - a.y) * (c.x - d.x)) / ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y)); contractPoint.y = ((b.y - a.y) * (c.y - d.y) * (c.x - a.x) - c.y * (b.y - a.y) * (c.x - d.x) + a.y * (b.x - a.x) * (c.y - d.y)) / ((b.x - a.x) * (c.y - d.y) - (b.y - a.y) * (c.x - d.x)); if ((contractPoint.x - a.x) * (contractPoint.x - b.x) <= 0 && (contractPoint.x - c.x) * (contractPoint.x - d.x) <= 0 && (contractPoint.y - a.y) * (contractPoint.y - b.y) <= 0 && (contractPoint.y - c.y) * (contractPoint.y - d.y) <= 0) { //Debug.Log("线段相交于点(" + contractPoint.x + "," + contractPoint.z + ")!"); return 1; // '相交 } else { //Debug.Log("线段相交于虚交点(" + contractPoint.x + "," + contractPoint.z + ")!"); return -1; // '相交但不在线段上 } } }