Unity Text 插入图片

标签: unity ui
17366人阅读 评论(29) 收藏 举报
分类:
当前测试版本:Unity 5.2.0

Unity 新 UI 系统中的 Text 组件支持富文本标签,标签包括 b(黑体)、i(斜体)、size(大小)、color(颜色),并不支持图片的直接插入。但官方文档提到可以对 Text Mesh 插入贴图,文档说明如下:
quad
 
This is only useful for text meshes and renders an image inline with the text. It takes parameters that specify the material to use for the image, the image height in pixels, and a further four that denote a rectangular area of the image to display. Unlike the other tags, quad does not surround a piece of text and so there is no ending tag - the slash character is placed at the end of the initial tag to indicate that it is “self-closing”.
 
   <quad material=1 size=20 x=0.1 y=0.1 width=0.5 height=0.5 />
 
This selects the material at position in the renderer’s material array and sets the height of the image to 20 pixels. The rectangular area of image starts at given by the x, y, width and height values, which are all given as a fraction of the unscaled width and height of the texture.

即 Text Mesh 上可以在文本内插入一张图片,参数 material 表示所要插入图片的材质下标。

创建一个 3D Text 对象,如下所示:

在 Assets 目录下,创建一个空材质,材质设置如下:

对 Mesh Renderer 添加这个材质,然后设置 Text Mesh 的 Text 属性为
1
Hello<quad material=1 size=20 x=0.1 y=0.1 width=0.5 height=0.5 />World
效果为如下所示:

重新设置 Text Mesh 的 Text 属性为
1
Hello<quad material=1 size=20 x=0 y=0 width=1 height=1 />World
效果为如下所示:

插入图片标签里面的属性 x 和 y 表示材质里图片的偏移位置,将会根据这两个值,对最后的图片进行反向偏移。width 和 height 表示图片未缩放前的比例,将会根据这两个值,对最后的图片进行缩放到原始比例。

uGUI 里面的 Text 组件无法使用这种方式插入图片,但是可以使用这种方式来变成占位符,最后再在占位符的位置放上所需要插入的图片。
占位符效果如下所示:

用下面的文本内容进行测试:
1
N<quad name=xb_b size=25 width=1 />
每个字母占4个顶点,即使是 quad 标签所占用的字符串,也要占用顶点数,如下图所示:

我们可以取标签最后所在的顶点,将图片放置于此坐标。新建一个类,派生自原生的 Text 类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine.UI;
 
public class TextPic : Text
{
    /// <summary>
    /// 图片池
    /// </summary>
    private readonly List<Image> m_ImagesPool = new List<Image>();
 
    /// <summary>
    /// 图片的最后一个顶点的索引
    /// </summary>
    private readonly List<int> m_ImagesVertexIndex = new List<int>();
 
    /// <summary>
    /// 正则取出所需要的属性
    /// </summary>
    private static readonly Regex s_Regex = 
          new Regex(@"<quad name=(.+?) size=(\d*\.?\d+%?) width=(\d*\.?\d+%?) />", RegexOptions.Singleline);
 
    public override void SetVerticesDirty()
    {
        base.SetVerticesDirty();
        UpdateQuadImage();
    }
 
    protected void UpdateQuadImage()
    {
        m_ImagesVertexIndex.Clear();
        foreach (Match match in s_Regex.Matches(text))
        {
            var picIndex = match.Index + match.Length - 1;
            var endIndex = picIndex * 4 + 3;
            m_ImagesVertexIndex.Add(endIndex);
 
            m_ImagesPool.RemoveAll(image => image == null);
            if (m_ImagesPool.Count == 0)
            {
                GetComponentsInChildren<Image>(m_ImagesPool);
            }
            if (m_ImagesVertexIndex.Count > m_ImagesPool.Count)
            {
                var resources = new DefaultControls.Resources();
                var go = DefaultControls.CreateImage(resources);
                go.layer = gameObject.layer;
                var rt = go.transform as RectTransform;
                if (rt)
                {
                    rt.SetParent(rectTransform);
                    rt.localPosition = Vector3.zero;
                    rt.localRotation = Quaternion.identity;
                    rt.localScale = Vector3.one;
                }
                m_ImagesPool.Add(go.GetComponent<Image>());
            }
 
            var spriteName = match.Groups[1].Value;
            var size = float.Parse(match.Groups[2].Value);
            var img = m_ImagesPool[m_ImagesVertexIndex.Count - 1];
            if (img.sprite == null || img.sprite.name != spriteName)
            {
                img.sprite = Resources.Load<Sprite>(spriteName);
            }
            img.rectTransform.sizeDelta = new Vector2(size, size);
            img.enabled = true;
        }
 
        for (var i = m_ImagesVertexIndex.Count; i < m_ImagesPool.Count; i++)
        {
            if (m_ImagesPool[i])
            {
                m_ImagesPool[i].enabled = false;
            }
        }
    }
 
    protected override void OnPopulateMesh(Mesh toFill)
    {
        base.OnPopulateMesh(toFill);
        var verts = toFill.vertices;
 
        for (var i = 0; i < m_ImagesVertexIndex.Count; i++)
        {
            var endIndex = m_ImagesVertexIndex[i];
            var rt = m_ImagesPool[i].rectTransform;
            var size = rt.sizeDelta;
            if (endIndex < verts.Length)
            {
                rt.anchoredPosition = new Vector2(verts[endIndex].x + size.x / 2, verts[endIndex].y + size.y / 2);
            }
        }
    }
}
不能够直接在 OnPopulateMesh 里面修改图片的大小,否则会报如下错误:
1
Trying to add Image (UnityEngine.UI.Image) for graphic rebuild while we are already inside a graphic rebuild loop. This is not supported.
最后效果如下所示:

图片根据标签里面的 name 属性来加载,从 Resources 目录读取。图片的大小通过 size 属性来控制。

但是,可以发现左下角有小黑点绘制,这是因为使用到了 quad 标签,但是没有用它底层的插入图片方式,所以“乱码”显示了小黑点。这里用更改顶点坐标方式来抹除,更改代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    protected override void OnPopulateMesh(Mesh toFill)
    {
        base.OnPopulateMesh(toFill);
        var verts = toFill.vertices;
 
        for (var i = 0; i < m_ImagesVertexIndex.Count; i++)
        {
            var endIndex = m_ImagesVertexIndex[i];
            var rt = m_ImagesPool[i].rectTransform;
            var size = rt.sizeDelta;
            if (endIndex < verts.Length)
            {
                rt.anchoredPosition = new Vector2(verts[endIndex].x + size.x / 2, verts[endIndex].y + size.y / 2);
 
                // 抹掉左下角的小黑点
                for (int j = endIndex, m = endIndex - 3; j > m; j--)
                {
                    verts[j] = verts[m];
                }
            }
        }
 
        if (m_ImagesVertexIndex.Count != 0)
        {
            toFill.vertices = verts;
            m_ImagesVertexIndex.Clear();
        }
    }
最后的效果如下:

测试例子如下:

当然离最后的使用,还需要进行进一步的修改。

Unity 5.2.2 接口更改,见下一篇文章《Unity Text 插入超链接》。



查看评论

Unity新UI系统概述——Rich Text

UI元素和text meshes的文本可以混合使用多种字体风格和大小。新的和旧的UI系统都支持富文本。Text,GUIStyle和TextMesh类都有用于指示Unity查询文本内部标记标签的富文本设...
  • u014630768
  • u014630768
  • 2014-11-29 19:34:18
  • 4480

Unity UGUI实现图文混排

目前在unity实现图文混排的好像都是通过自定义字体然后在文本获取字符的位置,用图片替换掉图片标签,这样对于支持英文来说,并没有什么影响。然后对于中文来说就是一个相当麻烦的事了,毕竟图文混排多用于游戏...
  • qq992817263
  • qq992817263
  • 2016-03-28 20:05:38
  • 18293

Unity UGUI图文混排(五) -- 一张图集对应多个Text

继上一篇说的更新了一张图集对应多个Text的功能,为了节省资源嘛 这里,但是也没有舍弃之前的一个Text一个图集,因为我感觉应该两个都有用,于是我重新写了一个脚本 1.其实大体跟前面的都没变,解析...
  • qq992817263
  • qq992817263
  • 2016-10-14 19:54:34
  • 3470

unity里面富文本的处理

在开发的过程中,想要对Text里面一段文字以特殊的颜色显示,又不想其他的地方受到影响,在4.6.3里面,text支持富文本,需要将试图里面讲该属性打钩。必须说  我们想要下面这一句话“ 我是游戏开发爱...
  • Monight_H
  • Monight_H
  • 2015-10-12 22:42:12
  • 2814

Unity UI(四):Text、Image/RawImage和Mask

TextText组件CharacterText:显示的文本 Font:字体 FontStyle:样式 LineSpacing:行间距,单位是行高 Rich Text:是否支持HTML标签。支持...
  • wkhabc
  • wkhabc
  • 2016-08-25 22:30:36
  • 2031

Unity Text 插入超链接

Unity 新 UI 系统中的 Text 组件支持富文本标签,标签包括 b(黑体)、i(斜体)、size(大小)、color(颜色),并不支持超链接以及超链接点击。之前一篇实现了简单的插入图片方法,见...
  • akof1314
  • akof1314
  • 2015-10-12 18:52:19
  • 12056

unity4.6 Ugui中文教程之UGUI Rich Text详解

http://bbs.9ria.com/thread-420408-1-1.html   7、Rich Text UI元素和文本网格的文本可以合并多个字体样式和大小。对 UI系统和传统的 GUI...
  • anypkv
  • anypkv
  • 2015-05-22 16:18:04
  • 1323

Unity3D在UI中加入Image图片

在将图片拖入到Assets后发现更本不能将图片拖入到UI中: 新建Image后在Source Image中也不能找到图片: 那是因为你没把图片设置为Sprite,图片只是Texture而已,只...
  • u014581901
  • u014581901
  • 2016-05-05 23:17:03
  • 21526

Unity3d ugui(1) 实现image代码换图

核心脚本代码 Image icon = transform.Find("icon").GetComponent(); Sprite sp = Resources.Load("Textrues/yutu...
  • swwa23
  • swwa23
  • 2016-08-18 11:49:08
  • 11018

【UGUI】UGUI 文字背景根据文字大小自适应

在使用UGUI 的时候经常会做文字的适配,就是当文字字数超出文本以后让文本随字体的数量增加而加长或加宽,当有背景去做适配的时候如何去做呢? 道理是一样的 在text + contentSiz...
  • ldy597321444
  • ldy597321444
  • 2017-09-13 17:48:34
  • 1090
    个人资料
    等级:
    访问量: 361万+
    积分: 3万+
    排名: 138
    文章存档
    最新评论