在Unity3D中实现高效的战斗飘字

42 篇文章 11 订阅
41 篇文章 0 订阅

版权所有,转载须注明出处!
喜欢火影、喜欢Java、喜欢unity3D、喜欢游戏开发的都可以加入木叶村Q群:379076227



这周有网友提到用NGUI做战斗冒血,冒伤害等文字性能太差。确实如此,我之前(NGUI 3.8.2,1000块的Android机器上)在Profile中也发现UIPanel占用CPU奇高。

因此最终自己在战斗飘文字这一块没有使用NGUI,而是自己创建Mesh来处理。优化前后在手机上每秒大概增加了10帧。


先看一下效果。


可以看到DrawCall和NGUI一样都为1。

这个 MeshText 就是我自己写的HUD文本组件了。


代码如下:

using UnityEngine;

[ExecuteInEditMode]
public class MeshText : MonoBehaviour
{
    [SerializeField]
    private string _text = "";

    public MeshFilter meshFilter;
    public MeshRenderer meshRenderer;



    [HideInInspector]
    public Material material;

    public UIAtlas uiAtlas;

    [SerializeField]
    private Color _color1 = Color.white;
    public Color color1
    {
        get { return _color1; }
        set { 
            _color1 = value;
        }
    }

    [SerializeField]
    private Color _color2 = Color.white;
    public Color color2
    {
        get { return _color2; }
        set
        {
            _color2 = value;
        }
    }

    public enum HorizontalAlignType
    {
        Left,
        Center,
        Right
    }

    //当text中存在宽度不一致的字体时,计算Center和Right会有误差。不过对于战斗HUD,够用了。
    public HorizontalAlignType HAlignType;
    public string Text {
        get { return _text; }
        set
        {
            _text = value;
            GenerateFilter();
        }
    }

    void Awake() {
#if UNITY_EDITOR
        meshRenderer.sharedMaterial = uiAtlas.spriteMaterial;
        material = meshRenderer.sharedMaterial;
#else
        meshRenderer.material = uiAtlas.spriteMaterial;
        material = meshRenderer.material;
#endif
        if (!string.IsNullOrEmpty(_text))
        {
            GenerateFilter();
        }
    }

    public void GenerateFilter() {
        Mesh mesh = new Mesh();

        int length = Text.Length;
        Vector3[] vertices = new Vector3[length<<2];
        Vector2[] uvs = new Vector2[vertices.Length];
        int[] triangles = new int[(length<<1)*3];
        Texture tex = uiAtlas.texture;
        Color[] colors = new Color[vertices.Length];
        int tmp = 0;
        float tmp2 = 0;
        switch (HAlignType)
        {
            case HorizontalAlignType.Center:
                tmp2 = - (vertices.Length >> 3);
                break;
            case HorizontalAlignType.Left:
                tmp2 = 0;
                break;
            case HorizontalAlignType.Right:
                tmp2 = -(vertices.Length >> 2);
                break;
            default:
                tmp2 = 0;
                break;
        }
        float r = 1;
        for (int i = 0; i < vertices.Length; i+=4) {
            tmp = (i + 1) % 2;

            string s = Text[i / 4].ToString();
            UISpriteData mSprite = uiAtlas.GetSprite(s);
            r = (mSprite.width * 1.0f / mSprite.height);
            //setting vertices
            vertices[i    ] = new Vector3( tmp2, tmp + 1 );
            vertices[i + 1] = new Vector3( tmp2, tmp );
            tmp2 += r;
            vertices[i + 2] = new Vector3( tmp2, tmp + 1 );
            vertices[i + 3] = new Vector3( tmp2, tmp );


            colors[i] = color1;
            colors[i+1] = color2;
            colors[i+2] = color1;
            colors[i+3] = color2;


            //setting uvs

            Rect inner = new Rect(mSprite.x + mSprite.borderLeft, mSprite.y + mSprite.borderTop,
                mSprite.width - mSprite.borderLeft - mSprite.borderRight,
                mSprite.height - mSprite.borderBottom - mSprite.borderTop);
            inner = NGUIMath.ConvertToTexCoords(inner, tex.width, tex.height);

            uvs[i] = new Vector2(inner.xMin, inner.yMax);
            uvs[i + 1] = new Vector2(inner.xMin, inner.yMin);
            uvs[i + 2] = new Vector2(inner.xMax, inner.yMax);
            uvs[i + 3] = new Vector2(inner.xMax, inner.yMin);
        }

        for (int i = 0; i < triangles.Length; i+=6) {
            tmp = (i / 3) << 1;
            triangles[i] = triangles[i + 3]  = tmp;
            triangles[i + 1] = triangles[i + 5] = tmp + 3;
            triangles[i + 2] = tmp + 1;
            triangles[i + 4] = tmp + 2;
        }
        mesh.vertices = vertices;
        mesh.colors = colors;
        mesh.triangles = triangles;
        mesh.uv = uvs;

        meshFilter.mesh = mesh;
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.gray;
        DrawMesh();
    }

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green;
        DrawMesh();
    }

    private void DrawMesh()
    {
        if (meshFilter == null)
        {
            return;
        }
        Mesh mesh = meshFilter.sharedMesh;
        if (mesh == null)
        {
            return;
        }
        int[] tris = mesh.triangles;
        for (int i = 0; i < tris.Length; i += 3)
        {
            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i]]), convert2World(mesh.vertices[tris[i + 1]]));
            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i]]), convert2World(mesh.vertices[tris[i + 2]]));
            Gizmos.DrawLine(convert2World(mesh.vertices[tris[i + 1]]), convert2World(mesh.vertices[tris[i + 2]]));
        }
    }

    private Vector3 convert2World(Vector3 src)
    {
        return transform.TransformPoint(src);
    }
}



关于这段代码应该没什么解释的,主要是关于三角形顶点计算、uv计算这些。随便找一篇创建Mesh的文章看完应该就可以看懂了。

虽然里面用到了NGUI的图集,但渲染和更新已经完全和NGUI无关了。

如果想改成不用NGUI的图集也可以。不过那时候比较懒,已经有图集了,就直接拿过来用咯。

不想用NGUI图集的可以自行修改掉。这样可以脱离NGUI运行。


完整工程(基于Unity3D 4.3.3 和 NGUI3.8.2测试)在这里:

链接: http://pan.baidu.com/s/1pKpalh5 密码: snpq


  • 14
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Unity3D实现鼠标悬浮模型上显示文字,可以使用Unity的鼠标事件和UI系统来实现。 首先,在模型上添加一个Collider组件,以便能够检测到鼠标事件。然后,在模型上添加一个空的GameObject作为子对象,用于显示文本。 接下来,创建一个脚本并将其附加到模型的Collider上。在脚本,使用OnMouseEnter和OnMouseExit函数来检测鼠标进入和离开事件。当鼠标进入时,启用子对象,并将其位置设置为鼠标所在的位置。同时,将子对象的UI Text组件的文本内容设置为要显示的文字。当鼠标离开时,禁用子对象。 下面是一个示例代码: ```csharp using UnityEngine; using UnityEngine.UI; public class HoverText : MonoBehaviour { public string textToShow; private GameObject hoverTextObject; private Text hoverText; void Start() { hoverTextObject = transform.GetChild(0).gameObject; hoverText = hoverTextObject.GetComponent<Text>(); } void OnMouseEnter() { hoverTextObject.SetActive(true); hoverText.text = textToShow; hoverTextObject.transform.position = Input.mousePosition; } void OnMouseExit() { hoverTextObject.SetActive(false); } } ``` 在上面的代码,我们通过transform.GetChild(0)来获取子对象,并使用GetComponent()函数来获取UI Text组件。在OnMouseEnter函数,我们设置了文本和位置,并启用了子对象。在OnMouseExit函数,我们禁用了子对象。 注意,在使用此方法时,需要为UI Text组件设置字体、颜色、大小等属性,以便能够正常显示文本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值