zoukankan      html  css  js  c++  java
  • Unity 检测物体是否在相机视野范围内

    摘要:本文原创,转载请注明出处:http://www.cnblogs.com/AdvancePikachu/p/6733620.html

    需求:

    类似NPC血条,当NPC处于摄像机视野内,血条绘制,且一直保持在NPC头顶。

    开始:

    网上查找资料,然后编写代码:

    public RectTransform rectBloodPos;
    
    void Update () 
        {
            this.gameObject.transform.Translate (Input.GetAxis ("Horizontal") * 10 * Time.deltaTime, 0, 0);
            this.gameObject.transform.Translate (0, 0, Input.GetAxis ("Vertical") * 10 * Time.deltaTime);
    
            Vector2 vec2 = Camera.main.WorldToScreenPoint (this.gameObject.transform.position);
            rectBloodPos.anchoredPosition = new Vector2 (vec2.x - Screen.width / 2 + 0, vec2.y - Screen.height / 2 + 60);        
        }

    实现效果图:

    但是随后发现,若摄像机背对物体则如下图:

    什么鬼,居然凭空出现UI,后来研究改进:

     1 bool isRendering;
     2     float curtTime=0f;
     3     float lastTime=0f;
     4 
     5     void OnWillRenderObject()
     6     {
     7         curtTime = Time.time;
     8     }
     9 
    10     void Update () 
    11     {
    12         isRendering = curtTime != lastTime?true:false;
    13 
    14         Vector2 vec2 = Camera.main.WorldToScreenPoint (this.gameObject.transform.position);
    15         if (isRendering)
    16         {
    17             rectBloodPos.gameObject.SetActive (true);
    18             rectBloodPos.anchoredPosition = new Vector2 (vec2.x - Screen.width / 2 + 0, vec2.y - Screen.height / 2 + 60);
    19         }
    20         else
    21             rectBloodPos.gameObject.SetActive (false);
    22 
    23         lastTime = curtTime;
    24 
    25     }

    这种方法的原理是,当摄像机范围内出现挂有该脚本的物体,且该物体上存在Render组件的,则触发绘制UI。

    虽然这个方法很好用,但是由于物体太多后,影响性能,故再次改进:

     1 public bool IsInView(Vector3 worldPos)
     2     {
     3         Transform camTransform = Camera.main.transform;
     4         Vector2 viewPos = Camera.main.WorldToViewportPoint (worldPos);
     5         Vector3 dir = (worldPos - camTransform.position).normalized;
     6         float dot = Vector3.Dot (camTransform.forward, dir);//判断物体是否在相机前面
     7 
     8         if (dot > 0 && viewPos.x >= 0 && viewPos.x <= 1 && viewPos.y >= 0 && viewPos.y <= 1)
     9             return true;
    10         else
    11             return false;
    12     }
    13 
    14     void Update () 
    15     {
    16         Vector2 vec2 = Camera.main.WorldToScreenPoint (this.gameObject.transform.position);
    17 
    18         if (IsInView (transform.position)) 
    19         {
    20             rectBloodPos.gameObject.SetActive (true);
    21             rectBloodPos.anchoredPosition = new Vector2 (vec2.x - Screen.width / 2 + 0, vec2.y - Screen.height / 2 + 60);
    22         }
    23         else
    24             rectBloodPos.gameObject.SetActive (false);
    25     }

    这个方法是用Vector3.Dot()的方法判断摄像机与物体的朝向以及前后从而判定是否显示UI。

    以上完美实现NPC血条跟随。

    如果小伙伴们有更好的方法,一定要记得分享啊!!!

  • 相关阅读:
    移动端阻止事件冒泡需要注意!
    JavaScript闭包
    JS原型与原型链终极讲解
    逐行分析jQuery源码
    jQuery源码分析-03构造jQuery对象-源码结构和核心函数
    screenX clientX pageX的区别
    JSON.stringify 语法实例讲解
    pipenv 简要指南
    webpy简单使用
    初识Dash -- 构建一个人人都能够轻松上手的界面,操控数据和可视化
  • 原文地址:https://www.cnblogs.com/AdvancePikachu/p/6733620.html
Copyright © 2011-2022 走看看