纳金网
标题:
【转】u3d NPC头顶姓名实现效果
[打印本页]
作者:
烟雨
时间:
2016-2-26 23:20
标题:
【转】u3d NPC头顶姓名实现效果
网上找了很多关于NPC头顶姓名的代码。
有OnGUI的,有用NGUI的
但是,都有一个共同的特点,就是只能进行2D视角的显示或者伪3D视角,在3D视角里存在着Z轴的影响,且相机的2D坐标里涉及相机的背对着NPC的情况。
因此,在绘制NPC姓名时出现了一个BUG,那就是即使背对着NPC方向,屏幕上也会出现NPC的姓名,导致玩家不能准确的找到NPC的位置。
话不多说,下面上代码
using UnityEngine;
using System.Collections;
public class NpcShowName : MonoBehaviour
{
//主角对象
private GameObject player;
//主摄像机对象
private Camera camera;
//NPC名称
private string name = "哥布林";
//NPC模型高度
private float npcHeight =1;
//是否进行NPC名称的绘制
private bool canlook=false;
//看见名称的距离
public int watchRange =20;
void Start ()
{
//根据Tag得到主角对象
player = GameObject.FindGameObjectWithTag("MainCamera");
camera = Camera.main;
}
void Update ()
{
float nowDistance = Vector3.Distance(transform.position, player.transform.position);
Debug.Log(canlook);
Debug.Log(nowDistance);
Rect screenRect = new Rect(0, 0, Screen.width, Screen.height);
Vector3 screenPos = camera.WorldToScreenPoint(transform.position);
if (!screenRect.Contains(screenPos) || nowDistance > watchRange) //不在屏幕上或者超出可视范围,则不显示名称
{
canlook = false;
}
else
{
canlook = true;
}
}
void OnGUI()
{
if (canlook)
{
//得到NPC头顶在3D世界中的坐标
//默认NPC坐标点在脚底下,所以这里加上npcHeight它模型的高度即可
Vector3 worldPosition = new Vector3(transform.position.x, transform.position.y + npcHeight, transform.position.z);
//根据NPC头顶的3D坐标换算成它在2D屏幕中的坐标
Vector3 position = camera.WorldToScreenPoint(worldPosition);
//得到真实NPC头顶的2D坐标
position = new Vector3(position.x, Screen.height - position.y,position.z);
//计算NPC名称的宽高
Vector2 nameSize = GUI.skin.label.CalcSize(new GUIContent(name));
//设置显示颜色为黄色
GUI.color = Color.red;
//绘制NPC名称
GUI.Label(new Rect(position.x - (nameSize.x / 2), position.y - nameSize.y, nameSize.x, nameSize.y), name);
}
}
void OnBecameVisible() //在相机范围内则进行渲染(即显示)
{
enabled = true;
canlook = true;
}
void OnBecameInvisible() //在相机范围外,则不进行渲染(即不显示)
{
enabled = false;
canlook = false;
}
}
复制代码
这里使用了两个重要的函数。 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坐标,再进行与屏幕的宽和高进行对比,判断是否在屏幕范围内(不是相机视野)。
好了,讲解就到这里。希望会对大家有帮助。有什么错误的地方请指正。相互学习。
欢迎光临 纳金网 (http://go.narkii.com/club/)
Powered by Discuz! X2.5