RPG 游戏 unity ngui 实现2D名字牌血条等功能

来源:互联网 发布:彩绘精灵mac 编辑:程序博客网 时间:2024/05/22 12:14

名字牌包括2D,3D名字牌两种,区别在于2D是基于屏幕坐标的名字牌,将名字牌的gameobject结点挂在UI相机下,不会受3D场景中物件的影响,3D名字牌可以视为游戏场景内的一部分物件,名字牌跟随角色移动同时也会被3D场景中其他物件遮挡,这里仅讨论2D名字牌

关于ngui实现名字牌的方式,很多博客都写到过,本人在这里针对RPG游戏中的实现方式进行一下个人总结

先归纳一下这类需求:

名字牌:玩家血条、个人昵称,帮派名称、称号 及其他XX等顶在角色头顶的,延伸需求涉及名字牌屏蔽功能,只显示一定范围的玩家名字牌,其他屏蔽,当角色跑到身后时进行视野裁剪,同时场景内角色管理时,从性能角度需要考虑仅显示一定数量上限的角色包括显示优先级,比如NPC和普通玩家、好友、家族成员,帮派成员,敌国玩家,这些角色达到一定数量时是否创建还是仅创建名字牌

伤害tips: 普通攻击,暴击、吸血等 ,涉及美术字,tips动画

掉落物品tips:击杀怪物或者打碎箱子爆出的场景内道具上加道具tips提示


相关功能点:

1,3d场景中角色位置是不断变化的,2D的名字牌需要将位置时时和3D中的坐标对应,角色向右移动,屏幕上的名字牌也要跟随移动,即3D坐标空间和2D空间通过屏幕位置进行转换,

3DCamera.WorldToScreenPoint
<pre name="code" class="csharp" style="font-family: Arial, Helvetica, sans-serif; padding: 5px; border: 1px dotted rgb(170, 170, 170); color: rgb(63, 63, 63); font-size: 14px; line-height: 30px; orphans: 2; widows: 2; background-color: rgb(246, 246, 246);">2DCamera.ScreenToWorldPoint
具体实现代码:
<pre name="code" class="csharp" style="font-family: Arial, Helvetica, sans-serif; padding: 5px; border: 1px dotted rgb(170, 170, 170); color: rgb(63, 63, 63); font-size: 14px; line-height: 30px; orphans: 2; widows: 2; background-color: rgb(246, 246, 246);">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()    {
<span style="white-space:pre"></span>//取得3D场景摄像机和UI相机        m_go3DCamera = GameObject.FindWithTag("MainCamera").GetComponent<Camera>();        m_go2DCamera = GameObject.Find("UI Root").transform.FindChild("Camera").GetComponent<Camera>();    }void Update () {
//每帧UPDATE时,计算3D场景中角色位置变化,通过计算得到2D空间中的坐标位置,重新设置此物件在屏幕坐标的位置        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;    }}

2:,视野裁剪:
<span style="white-space:pre"></span>当其他玩家或者怪物,NPC离开主角摄像机范围时,需要隐藏对应的名字牌方法:1,通过摄像机的<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">ViewportToWorldPoint 计算物体是否在屏幕坐标内</span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">方法:2,</span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">3,由于是用NGUI实现的,因此,将创建的名字牌,血条等放到UIRoot下,利于减少drawcall</span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">创建一个panel,将名字牌、血条、伤害tips 的prefab不添加panel,同时将同一类的uilabel uisprite深度尽量接近,利用unity 的自动合并材质的功能</span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">4,由于游戏中需要大量创建tips 名字牌、血条,频繁的创建和销毁gameobject会带来性能的损失,因此需要引入池技术,每种类型 血条 ,名字牌,普通攻击tips 美术字的暴击tips 等每种创建时从池中取得,销毁时由池负责,池并不是真正销毁,有可能是setvisible,有可能是localscale  为0 </span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);">5,美术字暴击tips 美术为了追求效果,一些暴击、吸血等tips需要用美术字,使用uifont将美术字制作成字库,通过key-value取得对应的美术字效果,如果单个引用美术字会引起drawcall的增加,</span>
<span style="color: rgb(51, 51, 51); font-size: 16px; line-height: 28px; white-space: pre-wrap; background-color: rgb(255, 255, 255);"></span><div style="font-family: Tahoma; padding: 0px; font-size: 14px; color: rgb(63, 63, 63); line-height: 30px; orphans: 2; widows: 2;">减少DrawCall:</div><div style="font-family: Tahoma; padding: 0px; font-size: 14px; color: rgb(63, 63, 63); line-height: 30px; orphans: 2; widows: 2;">NGUI内置合并DrawCall机制,同一个Panel下,不被打断的depth区间段,使用同样的Material,这些Widget可以被合并为一个DrawCall</div>



0 0
原创粉丝点击