ps:刚好项目要实现这个功能,翻了翻网上没有找到相关文章,自己就写了一个,有什么更好的建议还请多指教

实现思路:

1、检测物体是否移出屏幕外

这部分unity有现成API,OnBecameVisible,与OnBecameInvisible. 这两个函数可以检测,但脚本要挂在检测的物体上,物体要有render组件

2、确定ui边缘位置

物体世界坐标转为屏幕左边,计算屏幕中心点与物体屏幕坐标连线,与屏幕边缘相交的点.

3、判断与屏幕相交的线是哪一条

使用矩阵给目标物体建立新的坐标

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BeameF : MonoBehaviour
{//参照的摄像机GameObject m_camera;//目标名称string m_objName;//提示按钮是否出现bool m_isButtonDis = false;//提示按钮public GameObject m_Button0;//提示ui状态public enum Disstate{Left,Right,Up,Down}Disstate m_dis;void Start(){m_camera = GameObject.FindGameObjectWithTag("MainCamera");}void OnBecameVisible(){//提示按钮没有出现m_isButtonDis = false;Debug.Log(this.name + "+" + "Visible");//关闭按钮提示m_objName = this.name;InterativeButtonCueClose(m_objName);}void OnBecameInvisible(){Debug.Log(this.name + "+" + "Invisible");//目标坐标转屏幕坐标Vector2 objScreen = Camera.main.WorldToScreenPoint(this.transform.position);//屏幕中心点与屏幕边缘的交点Vector3 point = Point(objScreen);//摄像机位置下目标位置Vector3 m_targetV3 = CalUVByMatrix(MakeMatrix(this.transform.position, m_camera.transform.forward, m_camera.transform.up, m_camera.transform.right), m_camera.transform.position);//打开按钮提示m_objName = this.name;InterativeButtonCue(m_objName, m_targetV3, point);//提示按钮出现m_isButtonDis = true;}void Update(){if (m_isButtonDis){StartCoroutine(Detection());}else{//关闭按钮提示m_objName = this.name;InterativeButtonCueClose(m_objName);}}//协程减少检测频率IEnumerator Detection(){yield return new WaitForSeconds(0.5f);//目标坐标转屏幕坐标Vector2 objScreen = Camera.main.WorldToScreenPoint(this.transform.position);//屏幕中心点与屏幕边缘的交点Vector3 point = Point(objScreen);//摄像机位置下目标位置Vector3 m_targetV3 = CalUVByMatrix(MakeMatrix(this.transform.position, m_camera.transform.forward, m_camera.transform.up, m_camera.transform.right), m_camera.transform.position);//打开按钮提示m_objName = this.name;InterativeButtonCue(m_objName, m_targetV3, point);}/// <summary>/// 构建一个4x4的矩阵/// </summary>/// <param name="origin">新坐标空间的原点位置</param>/// <param name="forward">新坐标空间的Z轴</param>/// <param name="up">新坐标空间的Y轴</param>/// <param name="right">新坐标空间的X轴</param>private Matrix4x4 MakeMatrix(Vector3 origin, Vector3 forward, Vector3 up, Vector3 right){Matrix4x4 matrix = new Matrix4x4();Vector4 n_origin = new Vector4(origin.x, origin.y, origin.z, 1);Vector4 n_Z = new Vector4(forward.x, forward.y, forward.z, 0);Vector4 n_Y = new Vector4(up.x, up.y, up.z, 0);Vector4 n_X = new Vector4(right.x, right.y, right.z, 0);matrix.SetColumn(0, n_X);matrix.SetColumn(1, n_Y);matrix.SetColumn(2, n_Z);matrix.SetColumn(3, n_origin);return matrix;}/// <summary>/// 通过矩阵来建立新的坐标空间,来获取点的偏移/// </summary>/// <param name="matrix">坐标空间转换矩阵</param>/// <param name="target">需要转换的目标点</param>/// <returns></returns>private Vector3 CalUVByMatrix(Matrix4x4 matrix, Vector3 target){Vector4 pos = new Vector4(target.x, target.y, target.z, 1);matrix = matrix.inverse;Vector3 newPos = matrix * pos;return newPos;}/// <summary>/// 计算与屏幕交点/// </summary>/// <param name="_v2"></param>/// <returns></returns>Vector3 Point(Vector2 _v2){//判断物体与屏幕哪一边相交if (Mathf.Abs((_v2.x - (Screen.width / 2)) / (_v2.y - (Screen.height / 2))) > Mathf.Abs((Screen.width / 2) / (Screen.height / 2))){//与屏幕y轴相交//Debug.Log(Mathf.Abs(_v2.x / _v2.y) + "+" + Mathf.Abs((Screen.width / 2) / (Screen.height / 2)) + "+" + "y");Vector3 point;//计算边缘交点(交点z轴代表y轴)GetIntersection(new Vector3(Screen.width / 2, 0, Screen.height / 2), new Vector3(_v2.x, 0, _v2.y), new Vector3(Screen.width, 0, 0), new Vector3(Screen.width, 0, Screen.height), out point);return point;}else{//Debug.Log(Mathf.Abs(_v2.x / _v2.y) + "+" + Mathf.Abs((Screen.width / 2) / (Screen.height / 2)) + "+" + "x");//与屏幕x轴相交Vector3 point;//计算边缘交点(交点z轴代表y轴)GetIntersection(new Vector3(Screen.width / 2, 0, Screen.height / 2), new Vector3(_v2.x, 0, _v2.y), new Vector3(0, 0, Screen.height), new Vector3(Screen.width, 0, Screen.height), out point);return point;}return new Vector3(0, 0, 0);}/// <summary>/// 判断相交/// </summary>/// <param name="oneA"></param>/// <param name="oneB"></param>/// <returns></returns>public static int GetIntersection(Vector3 oneA, Vector3 oneB, Vector3 twoC, Vector3 twoD, out Vector3 contractPoint){//将4个端点置于同一水平面oneA.y = 0;oneB.y = 0;twoC.y = 0;twoD.y = 0;contractPoint = new Vector3(0, 0, 0);if (Mathf.Abs(oneB.z - oneA.z) + Mathf.Abs(oneB.x - oneA.x) + Mathf.Abs(twoD.z - twoC.z)+ Mathf.Abs(twoD.x - twoC.x) == 0){if ((twoC.x - oneA.x) + (twoC.z - oneA.z) == 0){Debug.Log("ABCD是同一个点!");}else{//Debug.Log("AB是一个点,CD是一个点,且AC不同!");}return 0;}if (Mathf.Abs(oneB.z - oneA.z) + Mathf.Abs(oneB.x - oneA.x) == 0){if ((oneA.x - twoD.x) * (twoC.z - twoD.z) - (oneA.z - twoD.z) * (twoC.x - twoD.x) == 0){//Debug.Log("A、B是一个点,且在CD线段上!");}else{//Debug.Log("A、B是一个点,且不在CD线段上!");}return 0;}if (Mathf.Abs(twoD.z - twoC.z) + Mathf.Abs(twoD.x - twoC.x) == 0){if ((twoD.x - oneB.x) * (oneA.z - oneB.z) - (twoD.z - oneB.z) * (oneA.x - oneB.x) == 0){//Debug.Log("C、D是一个点,且在AB线段上!");}else{//Debug.Log("C、D是一个点,且不在AB线段上!");}return 0;}if ((oneB.z - oneA.z) * (twoC.x - twoD.x) - (oneB.x - oneA.x) * (twoC.z - twoD.z) == 0){//Debug.Log("线段平行,无交点!");return 0;}if (oneA == twoC || oneA == twoD || oneB == twoC || oneB == twoD){//Debug.Log("两条线段有一个端点重合");return 0;}contractPoint.x = ((oneB.x - oneA.x) * (twoC.x - twoD.x) * (twoC.z - oneA.z) -twoC.x * (oneB.x - oneA.x) * (twoC.z - twoD.z) + oneA.x * (oneB.z - oneA.z) * (twoC.x - twoD.x)) /((oneB.z - oneA.z) * (twoC.x - twoD.x) - (oneB.x - oneA.x) * (twoC.z - twoD.z));contractPoint.z = ((oneB.z - oneA.z) * (twoC.z - twoD.z) * (twoC.x - oneA.x) - twoC.z* (oneB.z - oneA.z) * (twoC.x - twoD.x) + oneA.z * (oneB.x - oneA.x) * (twoC.z - twoD.z))/ ((oneB.x - oneA.x) * (twoC.z - twoD.z) - (oneB.z - oneA.z) * (twoC.x - twoD.x));if ((contractPoint.x - oneA.x) * (contractPoint.x - oneB.x) <= 0&& (contractPoint.x - twoC.x) * (contractPoint.x - twoD.x) <= 0&& (contractPoint.z - oneA.z) * (contractPoint.z - oneB.z) <= 0&& (contractPoint.z - twoC.z) * (contractPoint.z - twoD.z) <= 0){//Debug.Log("线段相交于点(" + contractPoint.x + "," + contractPoint.z + ")!");return 1; // '相交  }else{//Debug.Log("线段相交于虚交点(" + contractPoint.x + "," + contractPoint.z + ")!");return -1; // '相交但不在线段上  }}//提示ui显示public void InterativeButtonCue(string _name, Vector3 _targetV3, Vector3 _point){//ui状态if (Mathf.Abs(_targetV3.x) > Mathf.Abs(_targetV3.y)){if (_targetV3.x >= 0)m_dis = Disstate.Left;elsem_dis = Disstate.Right;}else{if (_targetV3.y >= 0)m_dis = Disstate.Up;elsem_dis =Disstate.Down;}CueFun(m_Button0, _point);m_Button0.SetActive(true);}//提示ui关闭public void InterativeButtonCueClose(string _name){m_Button0.SetActive(false);}//ui显示方法void CueFun(GameObject _button, Vector3 _point){//计算UI位置int m_py = (Screen.height / 2);int m_px = (Screen.width / 2);int m_uiSize = (int)_button.GetComponent<RectTransform>().rect.width / 2;//更改ui位置if (m_dis == Disstate.Left)_button.GetComponent<RectTransform>().localPosition = new Vector3(-_point.x / 2 + m_uiSize, -(_point.z - m_py), 0);else if (m_dis == Disstate.Right)_button.GetComponent<RectTransform>().localPosition = new Vector3(_point.x / 2 - m_uiSize, (_point.z - m_py), 0);else if (m_dis == Disstate.Up)_button.GetComponent<RectTransform>().localPosition = new Vector3(-(_point.x - m_px), -_point.z / 2 + m_uiSize, 0);else if (m_dis == Disstate.Down)_button.GetComponent<RectTransform>().localPosition = new Vector3(_point.x - m_px, _point.z / 2 - m_uiSize, 0);}}

注意:unity编辑下Scene窗口和Game窗口物体移出视口检测才有用.此脚本为了方便将所有内容整合在了一起

物体移出镜头外出现ui提示相关推荐

  1. 【Unity3D】点选物体、框选物体、绘制外边框

    1 需求描述 绘制物体外框线条盒子 中介绍了绘制物体外框长方体的方法,本文将介绍物体投影到屏幕上的二维外框绘制方法. 点选物体:点击物体,可以选中物体,按住 Ctrl 追加选中,选中的物体设置为红色. ...

  2. 【Unity】Unity实现鼠标控制摄像机围绕物体旋转镜头 滑轮控制远近

     在游戏和一些产品展示等项目中会有让摄像机围绕某个物体进行旋转这种需求  下面展示的代码是个删减版的  只保留了主要功能   限制的方面都删除了 在原有的代码中有  移动摄像机功能 围绕的点不做限制每 ...

  3. vscode element ui 提示 插件

    element-UI本身不难,但是vscode里面没有语法提示,对于写提示性的语句时真的太难受了. 我在vscode里找到了应该提示很强的elementUI提示库,Element UI Snippet ...

  4. 如何减少项目在Corona和V-Ray中的3ds Max渲染时间?

    相信在大多 3D 项目里,渲染是最耗费时间的部分,它不仅是建模和纹理化 3D 场景的过程,而是需要利用硬件来完成任务.我们在配备独立GPU和带有2到4个强大内核的CPU的中档计算机上,可以将3ds M ...

  5. 摄像头互动游戏-抓飞机躲炸弹

    国庆无聊,搞了一个摄像头互动类小游戏(宅男宅女们在紧张的面对电脑长时间后,抬起头来活动活动筋骨,挥舞双手抓飞机吧) 1.需要摄像头,灯光稍微好一些,背后最好有一面白色墙壁,以提高识别效果O(∩_∩)O ...

  6. APP提示框设计模板|UI设计师灵感好帮手

    提示框的作用 在细分提示框的种类之前,我想先说一下它的作用,提示框作为一个界面中的一个必不可少的组件,肯定是有它存在的独特的意义,独一无二,无法取代. 提示信息图片APP设计模板 提示框主要的作用有三 ...

  7. Unity3D插件 Doozy UI 学习(三):UI Element

    前言 之前写过一些关于DoozyUI的开发介绍,比较基础.后面用DoozyUI开发了一段时间,现在已经有了更深入的一些了解.这篇主要讲一下UI Elemenet这个脚本的使用. 正文 1.关于UI E ...

  8. 【UI/UX】深度解析模态窗口

    文章目录 前言 定义 用法 吸引用户注意力 需要用户输入 在界面环境中显示其他信息 显示其他信息(不在界面环境中) 模态窗口的剖析 逃生出口 描述性标题 按钮 尺寸和位置 焦点 用户启动 移动模式 辅 ...

  9. 三星android11推送,三星国行S10系列正式推送One UI 3正式版,基于安卓11打造

    三星国行S10系列正式推送One UI 3正式版,基于安卓11打造 2021-02-04 13:56:50 24点赞 15收藏 101评论 2月4日消息,今日,三星GALAXY盖乐世官方微博宣布,国行 ...

最新文章

  1. c语言万年历闹钟程序,c语言编写的万年历 有平年闰年 有闹钟功能.docx
  2. c++ thread 内存泄漏_使用 ThreadLocal如何避免内存泄露?
  3. JAVA复习5(总结+循环链表)
  4. linux so获取自己路径,linux下so获得自己文件位置的路径
  5. word字体放大后只显示一半_太实用了!5个Word冷门技巧!第3个你肯定不知道!...
  6. 资源描述框架RDF-阮一峰
  7. 【Oracle经典】132个oracle热门精品资料——下载目录
  8. python代码中函有中文报错的解决方法
  9. 抢椅子游戏java_抢椅子游戏作文(精选10篇)
  10. 移动机器人路径规划minimum_snap(MATLAB)笔记整理
  11. 计算机怎么知道用户名和密码,电脑的用户名和密码怎么查看
  12. 知识图谱学习(笔记整理)
  13. SpringBoot从入门到精通教程(二十九)- 微信企业支付集成(五分钟集成)
  14. android studio 小白使用记
  15. 自学C/C++如何入门
  16. 移动端 ios 字体偏上问题
  17. 在pdf文件中找关键字的坐标
  18. 百度推广客户端下载地址
  19. ORACLE 的触发器类型有哪些,ORACLE触发器类型
  20. Fuzz-AFL入门

热门文章

  1. 注册'@live.com'新方法!
  2. C语言入门Part7--数组篇
  3. http://playground.tensorflow.org游乐场摆弄网络思考
  4. 网络基础配置部署思路
  5. JavaScript 学习笔记(二)
  6. 千岛酱行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. Python习题十三套汇总
  8. 数据库之数据库和表的创建
  9. 09年中国网络广告:淘宝市场份额直逼新浪
  10. Invalid prop: type check failed for prop closeOnClickModal. Expected Boolean, got String with valu