查看: 966|回复: 0
打印 上一主题 下一主题

[其他] 【转】u3d NPC头顶姓名实现效果

[复制链接]

9903

主题

126

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
53488
精华
316

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

跳转到指定楼层
楼主
发表于 2016-2-26 23:20:46 |只看该作者 |倒序浏览
网上找了很多关于NPC头顶姓名的代码。有OnGUI的,有用NGUI的
但是,都有一个共同的特点,就是只能进行2D视角的显示或者伪3D视角,在3D视角里存在着Z轴的影响,且相机的2D坐标里涉及相机的背对着NPC的情况。
因此,在绘制NPC姓名时出现了一个BUG,那就是即使背对着NPC方向,屏幕上也会出现NPC的姓名,导致玩家不能准确的找到NPC的位置。

话不多说,下面上代码
  1. using UnityEngine;
  2. using System.Collections;

  3. public class NpcShowName : MonoBehaviour
  4. {
  5.     //主角对象
  6.     private GameObject player;
  7.     //主摄像机对象
  8.     private Camera camera;
  9.     //NPC名称
  10.     private string name = "哥布林";
  11.     //NPC模型高度
  12.     private float npcHeight =1;
  13.     //是否进行NPC名称的绘制
  14.     private bool canlook=false;
  15.     //看见名称的距离
  16.     public int watchRange =20;
  17.     void Start ()
  18.     {
  19.         //根据Tag得到主角对象
  20.       
  21.         player = GameObject.FindGameObjectWithTag("MainCamera");
  22.         camera = Camera.main;
  23.     }
  24.     void Update ()
  25.     {
  26.       
  27.       
  28.         float nowDistance = Vector3.Distance(transform.position, player.transform.position);
  29.         Debug.Log(canlook);
  30.         Debug.Log(nowDistance);
  31.       
  32.         Rect screenRect = new Rect(0, 0, Screen.width, Screen.height);
  33.         Vector3 screenPos = camera.WorldToScreenPoint(transform.position);
  34.         if (!screenRect.Contains(screenPos) || nowDistance > watchRange)  //不在屏幕上或者超出可视范围,则不显示名称
  35.         {
  36.             canlook = false;
  37.         }
  38.         else
  39.         {
  40.             canlook = true;
  41.         }

  42.       
  43.     }
  44.     void OnGUI()
  45.     {
  46.         if (canlook)
  47.             {

  48.             //得到NPC头顶在3D世界中的坐标
  49.             //默认NPC坐标点在脚底下,所以这里加上npcHeight它模型的高度即可
  50.             Vector3 worldPosition = new Vector3(transform.position.x, transform.position.y + npcHeight, transform.position.z);

  51.             //根据NPC头顶的3D坐标换算成它在2D屏幕中的坐标


  52.             Vector3 position = camera.WorldToScreenPoint(worldPosition);
  53.             //得到真实NPC头顶的2D坐标
  54.            position = new Vector3(position.x, Screen.height - position.y,position.z);
  55.             //计算NPC名称的宽高
  56.             Vector2 nameSize = GUI.skin.label.CalcSize(new GUIContent(name));
  57.             //设置显示颜色为黄色
  58.             GUI.color = Color.red;
  59.             //绘制NPC名称
  60.            
  61.                  GUI.Label(new Rect(position.x - (nameSize.x / 2), position.y - nameSize.y, nameSize.x, nameSize.y), name);
  62.             }
  63.         
  64.     }
  65.     void OnBecameVisible()  //在相机范围内则进行渲染(即显示)
  66.     {
  67.         enabled = true;
  68.         canlook = true;
  69.     }

  70.     void OnBecameInvisible() //在相机范围外,则不进行渲染(即不显示)
  71.     {
  72.         enabled = false;
  73.         canlook = false;
  74.     }
  75. }
复制代码
这里使用了两个重要的函数。 OnBecameVisible()和 OnBecameInvisible() 这是[color=rgb(85, 85, 85) !important]U3D自带的函数  (用于相机的渲染,是否是相机视野范围内)

然后提供了一个办法

Rect screenRect = new Rect(0, 0, Screen.width, Screen.height);        Vector3 screenPos = camera.WorldToScreenPoint(transform.position);        if (!screenRect.Contains(screenPos) || nowDistance > watchRange)  //不在屏幕上或者超出可视范围,则不显示名称

  这段代码是用来 把看到的物体的坐标转换为屏幕的2D坐标,再进行与屏幕的宽和高进行对比,判断是否在屏幕范围内(不是相机视野)。


     好了,讲解就到这里。希望会对大家有帮助。有什么错误的地方请指正。相互学习。

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-8-17 08:03 , Processed in 0.066054 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部