HUD区域限制算是比较常用到的功能,方形的HUD区域限制多见于小地图,弧形或者椭圆多见于屏幕范围约束。

我没有研究倒角矩形做法,而是将椭圆和矩形进行插值得到一个弧度比较高的形状:

当插值为0时限制范围是椭圆,插值为1限制范围是矩形

矩形的判断使用了线段相交函数,函数来自网络收集

线段相交: http://www.cnblogs.com/hont/p/6106043.html

代码如下

  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4.  
  5. public class HUDTest2 : MonoBehaviour
  6. {
  7. [Serializable]
  8. public class EllipseSetting
  9. {
  10. public float radius = 2f;
  11. public Vector2 scale = new Vector2(, );
  12. }
  13.  
  14. public Transform[] hudObjectArray;
  15. public EllipseSetting ellipseSetting = new EllipseSetting();
  16. [Range(, )]
  17. public float lerp;
  18.  
  19. void OnGUI()
  20. {
  21. for (int i = ; i < hudObjectArray.Length; i++)
  22. {
  23. var item = hudObjectArray[i];
  24.  
  25. var screenPosition = Camera.main.WorldToScreenPoint(item.transform.position);
  26. screenPosition.z = ;
  27. screenPosition.y = Screen.height - screenPosition.y;
  28. screenPosition = HUDFix(screenPosition);
  29.  
  30. GUI.Box(new Rect(screenPosition, Vector3.one * ), "");
  31. }
  32. }
  33.  
  34. Vector3 HUDFix(Vector3 position)
  35. {
  36. var center = new Vector3(Screen.width, Screen.height, ) * 0.5f;
  37.  
  38. var ellipsePoint = GetEllipsePoint(position);
  39. var quadPoint = GetRectPoint(position);
  40.  
  41. var finalPoint = Vector3.Lerp(ellipsePoint, quadPoint, lerp);
  42.  
  43. if (Vector3.Distance(center, finalPoint) >= Vector3.Distance(center, position))
  44. return position;
  45. else
  46. return finalPoint;
  47. }
  48.  
  49. Vector3 GetEllipsePoint(Vector3 currentPoint)
  50. {
  51. var center = new Vector3(Screen.width, Screen.height, ) * 0.5f;
  52. var current = center + (currentPoint - center).normalized * ellipseSetting.radius;
  53.  
  54. current.x *= ellipseSetting.scale.x;
  55. current.y *= ellipseSetting.scale.y;
  56.  
  57. return current;
  58. }
  59.  
  60. Vector3 GetRectPoint(Vector3 currentPoint)
  61. {
  62. var center = new Vector3(Screen.width, Screen.height, ) * 0.5f;
  63.  
  64. const float INNER = ;
  65. const float RAY = * ;
  66. var p0 = new Vector3(INNER, INNER, );
  67. var p1 = new Vector3(Screen.width - INNER, INNER, );
  68. var p2 = new Vector3(INNER, Screen.height - INNER, );
  69. var p3 = new Vector3(Screen.width - INNER, Screen.height - INNER, );
  70.  
  71. var dir = (currentPoint - center).normalized * RAY;
  72.  
  73. var contractPoint = default(Vector3);
  74. var r = GetIntersection(p0, p1, center, center + dir, out contractPoint);
  75. if (r == )
  76. return contractPoint;
  77.  
  78. r = GetIntersection(p1, p3, center, center + dir, out contractPoint);
  79. if (r == )
  80. return contractPoint;
  81.  
  82. r = GetIntersection(p0, p2, center, center + dir, out contractPoint);
  83. if (r == )
  84. return contractPoint;
  85.  
  86. GetIntersection(p2, p3, center, center + dir, out contractPoint);
  87. return contractPoint;
  88. }
  89.  
  90. int GetIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d, out Vector3 contractPoint)
  91. {
  92. contractPoint = new Vector3(, );
  93.  
  94. if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) + Mathf.Abs(d.y - c.y)
  95. + Mathf.Abs(d.x - c.x) == )
  96. {
  97. if ((c.x - a.x) + (c.y - a.y) == )
  98. {
  99. //Debug.Log("ABCD是同一个点!");
  100. }
  101. else
  102. {
  103. //Debug.Log("AB是一个点,CD是一个点,且AC不同!");
  104. }
  105. return ;
  106. }
  107.  
  108. if (Mathf.Abs(b.y - a.y) + Mathf.Abs(b.x - a.x) == )
  109. {
  110. if ((a.x - d.x) * (c.y - d.y) - (a.y - d.y) * (c.x - d.x) == )
  111. {
  112. //Debug.Log("A、B是一个点,且在CD线段上!");
  113. }
  114. else
  115. {
  116. //Debug.Log("A、B是一个点,且不在CD线段上!");
  117. }
  118. return ;
  119. }
  120. if (Mathf.Abs(d.y - c.y) + Mathf.Abs(d.x - c.x) == )
  121. {
  122. if ((d.x - b.x) * (a.y - b.y) - (d.y - b.y) * (a.x - b.x) == )
  123. {
  124. //Debug.Log("C、D是一个点,且在AB线段上!");
  125. }
  126. else
  127. {
  128. //Debug.Log("C、D是一个点,且不在AB线段上!");
  129. }
  130. return ;
  131. }
  132.  
  133. if ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y) == )
  134. {
  135. //Debug.Log("线段平行,无交点!");
  136. return ;
  137. }
  138.  
  139. contractPoint.x = ((b.x - a.x) * (c.x - d.x) * (c.y - a.y) -
  140. c.x * (b.x - a.x) * (c.y - d.y) + a.x * (b.y - a.y) * (c.x - d.x)) /
  141. ((b.y - a.y) * (c.x - d.x) - (b.x - a.x) * (c.y - d.y));
  142. contractPoint.y = ((b.y - a.y) * (c.y - d.y) * (c.x - a.x) - c.y
  143. * (b.y - a.y) * (c.x - d.x) + a.y * (b.x - a.x) * (c.y - d.y))
  144. / ((b.x - a.x) * (c.y - d.y) - (b.y - a.y) * (c.x - d.x));
  145.  
  146. if ((contractPoint.x - a.x) * (contractPoint.x - b.x) <=
  147. && (contractPoint.x - c.x) * (contractPoint.x - d.x) <=
  148. && (contractPoint.y - a.y) * (contractPoint.y - b.y) <=
  149. && (contractPoint.y - c.y) * (contractPoint.y - d.y) <= )
  150. {
  151.  
  152. //Debug.Log("线段相交于点(" + contractPoint.x + "," + contractPoint.z + ")!");
  153. return ; // '相交
  154. }
  155. else
  156. {
  157. //Debug.Log("线段相交于虚交点(" + contractPoint.x + "," + contractPoint.z + ")!");
  158. return -; // '相交但不在线段上
  159. }
  160. }
  161. }

两种屏幕HUD区域限制的做法(矩形,弧形)的更多相关文章

  1. 设置一个DIV块固定在屏幕中央(两种方法)

    设置一个DIV块固定在屏幕中央(两种方法) 方法一: 对一个div进行以下设置即可实现居中. <style> #a{ position: fixed; top: 0px; left: 0p ...

  2. jqGrid中实现radiobutton的两种做法

    http://blog.sina.com.cn/s/blog_4f925fc30102e27j.html   jqGrid中实现radiobutton的两种做法 ------------------- ...

  3. SqlServer保留几位小数的两种做法

    SqlServer保留几位小数的两种做法   数据库里的 float momey 类型,都会精确到多位小数.但有时候 我们不需要那么精确,例如,只精确到两位有效数字. 解决: 1. 使用 Round( ...

  4. HTML5工具做屏幕自适应的两种方法

    近一两年,HTML5在中国很火,也出了不少HTML5工具和模板.别的先不说,对于不同的H5工具,解决屏幕自适应问题的区别是什么? 简单来说,感应式设计是当用不同设备访问时,能够根据设备的宽度和高度对设 ...

  5. LVS+keepalived 的DR模式的两种做法

    LVS DR模式搭建 准备工作 三台机器: dr:192.168.13.15 rs1:192.168.13.16 rs2: 192.168.13.17 vip:192.168.13.100 修改DR上 ...

  6. Android 高级UI设计笔记23:Android 夜间模式之 两种常用方法(降低屏幕亮度+替换theme)

    1. 夜间模式 所谓的夜间模式,就是能够根据不同的设定,呈现不同风格的界面给用户,而且晚上看着不伤眼睛.特别是一些新闻类App实现夜间模式是非常人性化的,增强用户体验. 2. 我根据网上的资料 以及自 ...

  7. [正经分析] DAG上dp两种做法的区别——拓扑序与SPFA

    在下最近刷了几道DAG图上dp的题目. 要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点. 第二道是洛谷上的NOI导刊题目<最长路 ...

  8. CSS实现自适应不同大小屏幕的背景大图的两种方法(转自简书)

    CSS实现自适应不同大小屏幕的背景大图的两种方法 一张清晰漂亮的背景图片能给网页加分不少,设计师也经常会给页面的背景使用大图,我们既不想图片因为不同分辨率图片变形,也不希望当在大屏的情况下,背景有一块 ...

  9. Android 截取手机屏幕两种实现方案解析

    近期在开发的过程中,遇到了一个须要截取屏幕保存为图片的需求,详细为截取webview的视图保存图片. 方法1:首先想到的思路是利用SDK提供的View.getDrawingCache()方法: pub ...

随机推荐

  1. 修改Ubuntu默认运行级别,启动字符界面

    Ubuntu的默认开机的runlevel是2,可以用runlevel来查看当前的默认运行级别. debian系(ubuntu是基于debian)的Linux一直是用runlevel 2来默认启动,并且 ...

  2. Azure编程笔记(3):用Fiddler调试Azure的应用程序

     内容提要 Azure的服务是通过RESTfulAPI提供的. 尽管Azure针对非常多编程语言都提供了SDK.但这些SDK也仅仅是RESTfulAPI的一层封装. 在调用SDK或者RESTful ...

  3. 【DB2】查看表空间对应的物理文件地址

    使用的命令: db2 list tablespaces show detail db2 list tablespace containers for [Tablespace ID] [show det ...

  4. android应用Theme(二)

    另外一种实现android应用Theme的方式是通过apk来实现的. 以下是一个demo. 1.首先必须新建一个apk.类似的插件,然后在该apk的AndroidManifest.xml文件的appl ...

  5. Oracle的悲观锁和乐观锁

    为了得到最大的性能,一般数据库都有并发机制,不过带来的问题就是数据访问的冲突.为了解决这个问题,大多数数据库用的方法就是数据的锁定. 数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁.什么叫 ...

  6. java非web应用修改 properties/xml配置文件后,无需重启应用即可生效---自动加载

    实现时主要使用Commons-Configuration.jar包,还需要commons-lang,disgestor,beanutils,collections等, package propFile ...

  7. HDUOJ-----1074 Integer Inquiry

    Integer Inquiry Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...

  8. Python字典按值排序的方法

    Python字典按值排序的方法: 法1: (默认升序排序,加  reverse = True 指定为降序排序) # sorted的结果是一个list dic1SortList = sorted( di ...

  9. 为Magento1.5新增会员注册字段(转)

    第一步.新建一个模块,在app/etc/modules/目录下新建文件Shuishui_Customer.xml <config> <modules> <Shuishui ...

  10. Centos 安装ImageMagick 与 imagick for php步骤详解

    现在有很多朋友在使用安装ImageMagick imagick for php了,今天自己也想做但是不知道如何操作,下面我来给大家介绍Centos 安装ImageMagick imagick for ...