Unity里名字牌、血条等头顶挂件的实现

Unity里实现人物头顶的名字牌、血条的实现,网上很多博客有提到过。这里结合自己在项目中的开发,简单总结几点。

宣雨松的热门博客里有提到过直接利用Unity自身的OnGUI()实现人物血条:http://www.xuanyusong.com/archives/1032 。

撇开血条进度条的更新,重点关注头顶物件位置的更新。简化之,实现人物头顶的名字牌的。

核心代码如下:

using UnityEngine;
using System.Collections;

public class Following : MonoBehaviour {

    public Camera m_Camera = null;
    public GameObject m_goFollowing = null;
    public Vector3 m_vOffset;

    void OnGUI()
    {
        Vector3 vPosScreen = m_Camera.WorldToScreenPoint(m_goFollowing.transform.position + m_vOffset);
        GUI.Label(new Rect(vPosScreen.x, Screen.height - vPosScreen.y, 200, 80), "牧羊少年奇幻之旅");
    }

不过,实际项目中暂时不会用Unity的原生UI,目前的项目多用的是Unity4.x版本,原生UI太难用,多用NGUI等插件。下面主要介绍Unity中借助NGUI实现人物的头顶挂件。

头顶物件用NGUI实现可以根据渲染相机来分为两种方式:

(1)采用渲染场景的MainCamera来渲染头顶物件,这样的头顶物件可以看做普通的3D物体,是可以被场景中3D物体遮挡的。

(2)专门用UI相机渲染,头顶物件作为UI,不会被场景中3D物体遮挡。

一般我们会采用方式2,UI尽量不要用主相机渲染,用专门的UI相机渲染。

不过,还是顺带提一下采用方式(1)处理UI的核心代码:

public class Following : MonoBehaviour {
    public GameObject m_goFollowing = null;
    public float m_fOffset = 0;

    void Update()
    {
        gameObject.transform.position = m_goFollowing.transform.position + new Vector3(0, m_fOffset, 0);
        gameObject.transform.rotation = Camera.main.transform.rotation;
    }
}

如果您在实践中发现UILabel不可见,请注意:

(1)UILabel UISprite不能单独用,一定要附带一个Panel,作为Panel的子节点或者NGUIPanel和UILabel UISprite挂在同一个GameObject下。

(2)同时UILabel的Layer必须和所附带的NGUIPanel保持一致。请保证你的相机没有屏蔽UILabel所在的Layer。

(3)UILabel UISprite无论是在哪个Panel下,尽量放在UIRoot下吧。若有些物体看不见,调整下Scale。

我们一般采用方式2,UI用专门的UI相机渲染,核心是将主相机下的Transform映射到UI相机下的Transform。

using UnityEngine;
using System.Collections;

public class Following : MonoBehaviour {

    public GameObject m_goFollowing = null;
    public float m_fOffset = 0;
    private Camera m_go3DCamera = null;
    private Camera m_go2DCamera = null;

    void Start()
    {
        m_go3DCamera = GameObject.FindWithTag("MainCamera").GetComponent<Camera>();
        m_go2DCamera = GameObject.Find("UI Root").transform.FindChild("Camera").GetComponent<Camera>();
    }
void Update () {
        Vector3 vPos = TransPos(m_goFollowing.transform.position + new Vector3(0, m_fOffset, 0));
        gameObject.transform.position = new Vector3(vPos.x, vPos.y, 0);    //get proper z,  z = 0.0f simply
        gameObject.transform.rotation = m_go2DCamera.transform.rotation;   //keep the same rotation with camera, so Parallel with camera
}

    //Transform WorldPos in 3DCamera to new WorldPos in 2DCamera. They share the same ScreenPos
    Vector3 TransPos(Vector3 worldpos)
    {
        if (m_go3DCamera == null || m_go2DCamera == null)
        {
            return Vector3.zero;
        }
        Vector3 screenPos = m_go3DCamera.WorldToScreenPoint(worldpos);
        Vector3 newWorldPos = m_go2DCamera.ScreenToWorldPoint(screenPos);
        return newWorldPos;
    }
}

这其中的要点都写在注释里了。

游戏场景一般用3DCamera渲染,名字牌血条等属于UI,应该被UI相机渲染。头顶的名字牌血条要跟随着3D场景里的物体,关键是如何将3D相机空间里的位置映射到UI相机相机空间。中间的桥梁是屏幕位置,两个相机看到的头顶物件应该映射到同一个屏幕坐标。

同时,两个细节需要注意:

1. 为保证UI可见,通过UI相机变换得到的坐标深度要设置为合适的值,太远或太近会出视野范围。可以简单地设置为0。

2. 头顶物件要注意和UI相机保持平行,即头顶物件的rotation设置为UI相机的rotation。

实际应用中,还有一些性能问题需要注意。

(1)减少DrawCall:

NGUI内置合并DrawCall机制,同一个Panel下,不被打断的depth区间段,使用同样的Material,这些Widget可以被合并为一个DrawCall。

具体而言,使用同样的Atlas的UISprite,挂在同一个UIPanel下的depth区间,此depth区间在此UIPanel下不被其他的Atlas使用。UILabel也针对每种字体分配一个Depth区间。 当然,前提是不影响功能需求。

以头顶的名字条NameBar、血条HPBar为例,NameBar.prefab, HPBar.prefab本身不要带有UIPanel,我们为头戴物件在NGUI-UIRoot下创建一个共同的UIPanel--HeadWearingPanel,所有实例化的NameBar、HPBar都挂在HeadWearingPanel下。

另外,NGUI3.8.0之前的版本,显示/隐藏UIWdget会导致所有UIDrawCall的销毁重建,对CPU负荷较大。如果用NGUI3.8.0之前的版本,建议不要直接用gameObejct.SetActive(false)来实现UI控件的隐藏,可以令transform.scale = Vector3.zero, 或者将欲隐藏的UI移到视野外。NGUI3.8.0的版本没有这个问题了。

(2)减少GC

对于要频繁创建销毁的UI,做一个资源池。避免频繁创建销毁对象带来的大量gc。

针对每种类型的Prefab创建一个Pool.删除NameBar、HPBar时,并不真正Destroy,将之隐藏即可。常见NameBar、HPBar时,先从Pool里查找是否有可用的NameBar、HPBar,若没有找到才真正实例化创建新对象。

时间: 2024-12-26 10:51:41

Unity里名字牌、血条等头顶挂件的实现的相关文章

unity中简单的血条自作

unity中制作血条有很多方法,多数用NGUI:这里我就说说一个简单的血条制作方法吧: 这个血条制作不像NGUI一样,它是靠一段代码就可以实现的,但看起来比较效果比较差,还是看代码吧:  public Texture2D bg;     //血条的背景,需要在外面进行拖拽赋值:  public Texture2D blood;   //血条  float Life=100;            //总的生命值:    public Transform m_Transform;  //绑定血条的

Unity UGUI Canvas 使用Slider制作角色血条

最近课程实训选修Unity,讲解的是Unity官方案例--SpaceShoot,培训无聊,便想着给游戏角色制作一下血条,以此增加游戏的可玩性. Unity版本:5.4.1 案例模版:太空射击 原文作者:茄阁云云 原文连接:http://www.cnblogs.com/vmoor2016/p/6044941.html 把一个大象装进冰箱里需要三步:①把冰箱门打开:②把大象塞冰箱里:③关上冰箱门. 那么制作一个角色的血条需要几部呢?在这里也划分为三步:①制作血条:②摆放血条:③操作血条. 下面就来给

使用 NGUI 实现头顶文字及血条

以下是 NGUI HUD Text 实现的: 基本原理: 1. 在角色头顶绑一个点 Pivot,用于对齐 2. 因为界面总是覆盖在人物头顶信息的上面,所以将 UIRoot 分为2个 Panel:1) GUI,用于画界面,Depth 较大 2) HUDPanel,用于画人物头顶文字及血条,Depth 较小 (1和2是最重要的) 3. 先使用 NGUI 实现一套管理人物头顶信息的类(或若干个类),名为 HUDText,他包含了各种功能(设置名字.名字颜色.血条等) 4. 将 HUDText 存为 P

unity制作简单血条

学习Unity已经10天了,也没发现有什么长进,真的急.昨天仿着官方Demo做了个射击游戏轮廓,其中需要给每个怪做一个血条. 搜了一些,挺复杂的,用NGUI或者UGUI,外加很长的代码...不过还是找到了一篇简单的. 但是那一篇把所有的东西都放一起了,不太好,我在这整理分离一下. 背景: 官方Demo恶魔射手.其中每个怪都有一个EnemyHealth脚本,该脚本主要有怪物的血量等,然后有个TakeDamage()函数来计算伤害后的血量. 开始: 1.制作图片: PS一张细长的红色图片作为血量:

Unity3D人物头顶名称与血条更新与绘制

using UnityEngine; using System.Collections; public class NPC : MonoBehaviour { //主摄像机对象 private Camera camera; //NPC名称 private string name = "我是雨松MOMO"; //主角对象 GameObject hero; //NPC模型高度 float npcHeight; //红色血条贴图 public Texture2D blood_red; //黑

unity如何显示血条(不使用NGUI)

用unity本身自带的功能,如何显示血条? 显示血条,从资源最小化的角度,只要把一个像素的色点放大成一个矩形就足够,三个不同颜色的矩形,分别显示前景色,背景色,填充色,这样会消耗最少的显存资源. unity 有GUITexture,可以用来显示色块.但GUITexture有个问题是,每个GUITexture都会消耗一个drawcall,如果画面上就数百个单位,就会消耗数百个drawcall,drawcall是昂贵的资源,一个手游也就只能允许200个左右的drawcall,显然这个方案只能用来做d

【FairyGUI &amp; Unity】使用动效功能实现血条UI扣血与加血的缓动效果

原理 血条使用进度条组件,可以得到当前值与最大值. 通过动效-改变缩放可以让图片宽度从1到0按百分比变化. 动效可以指定播放动效的时间范围 组件设计 创建一个进度条组件,作为血条. bar是实际血量条 DownBar是扣血缓动背景图层 UpBar是加血缓动背景图层 LowBar是低血量变色(和控制器配合,本文不讲) n11组合是血量参考线 发布到Unity. 参考代码 if (hpValue < hpBar.value) // HP降低 { hpBar.DownBar.SetScale((flo

[Unity3D]Unity3D再叙NGUI之血条及技能冷却效果

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei. 转载请注明出处,本文作者:

Unity3d人物的名称与血条的绘制方法

人物的名称与血条的绘制方法很简单,但是我们需要解决的问题是如何在3D世界中寻找合适的坐标.因为3D世界中的人物是会移动的,它是在3D世界中移动,并不是在2D平面中移动,但是我们需要将3D的人物坐标换算成2D平面中的坐标,继而找到人物头顶在屏幕中的2D坐标最后使用GUI将名称与血条绘制出来. 首先学习本文的重点内容,如何将游戏世界中任意3D坐标转换成屏幕中的2D坐标.根据这个方法计算出的2D坐标屏幕左下角的点为0.0 ,屏幕右上角的坐标为1.1 所以真实的2D坐标还得通过Screen.height