Fork me on Gitee

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血条跟随。

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

 

posted @ 2017-04-19 15:13  AdvancePikachu  阅读(11132)  评论(5编辑  收藏  举报