实现在文本中插入图片,图片替换符使用如下格式 //XML: <quad index=0 size=60> 代码中<quad index=0 size=60>
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Text))]
public class TextTagHook : BaseMeshEffect
{
public class SpriteTagInfo
{
public int index;
public int stringIndex;
public Vector2 size;
public bool isVisible = true;
}
//in XML: <quad index=0 size=60> <quad index=0 size=60>
private static readonly Regex spriteTagRegex = new Regex(@"<quad\s+index=(\d+)\s+size=(\d*\.?\d+%?)(\s+width=(\d*\.?\d+%?))?\s*>", RegexOptions.Singleline);
private static readonly Regex spriteTagReplacementRegex = new Regex(@"{}", RegexOptions.Singleline);
private static readonly Regex tagRegex = new Regex(@"<.*?>", RegexOptions.Singleline);
private static readonly Regex whitespaceRegex = new Regex(@"\s+", RegexOptions.Singleline);
public RectTransform[] tagObjects = new RectTransform[] { };
private Text _text;
public Text text
{
get
{
if (_text == null)
{
_text = GetComponent<Text>();
}
return _text;
}
}
private List<SpriteTagInfo> spriteTags = new List<SpriteTagInfo>();
private string lastContent;
private bool lastBestFit;
private int lastVertexCount;
private bool isContentDirty
{
get
{
return true;
}
}
private bool isValid;
public override void ModifyMesh(VertexHelper vh)
{
if (!IsActive()) return;
if (isContentDirty)
{
lastContent = text.text;
lastBestFit = text.resizeTextForBestFit;
lastVertexCount = text.cachedTextGenerator.vertexCount;
spriteTags.Clear();
try
{
foreach (Match match in spriteTagRegex.Matches(lastContent))
{
SpriteTagInfo spriteTag = new SpriteTagInfo();
spriteTag.index = int.Parse(match.Groups[1].Value);
spriteTag.stringIndex = match.Index;
spriteTag.size = new Vector2(float.Parse(match.Groups[2].Value), float.Parse(match.Groups[2].Value));
if (match.Groups[4].Success)
{
spriteTag.size.x *= float.Parse(match.Groups[4].Value);
}
spriteTag.isVisible = text.cachedTextGenerator.vertexCount / 4 > spriteTag.stringIndex;
spriteTags.Add(spriteTag);
}
if (text.cachedTextGenerator.vertexCount / 4 != text.cachedTextGenerator.characterCount)
{
string toGenerateContent = spriteTagRegex.Replace(lastContent, "{}");
toGenerateContent = tagRegex.Replace(toGenerateContent, string.Empty);
toGenerateContent = whitespaceRegex.Replace(toGenerateContent, string.Empty);
int index = 0;
foreach (Match match in spriteTagReplacementRegex.Matches(toGenerateContent))
{
spriteTags[index].stringIndex = match.Index - index;
spriteTags[index].isVisible = true;
index++;
}
}
isValid = true;
}
catch (System.Exception e)
{
isValid = false;
}
}
for (int i = 0; i < tagObjects.Length; i++)
{
if (tagObjects[i] != null)
{
tagObjects[i].localScale = Vector3.zero;
}
}
if (isValid)
{
for (int i = 0; i < spriteTags.Count; i++)
{
SpriteTagInfo spriteTag = spriteTags[i];
if (tagObjects.Length > spriteTag.index)
{
var target = tagObjects[spriteTag.index];
if (target == null) continue;
if (spriteTag.isVisible)
{
float unitsPerPixel = 1 / text.pixelsPerUnit;
var verts = text.cachedTextGenerator.verts;
Vector2 roundingOffset = new Vector2(verts[0].position.x, verts[0].position.y) * unitsPerPixel;
roundingOffset = text.PixelAdjustPoint(roundingOffset) - roundingOffset;
Vector3 pox1 = verts[spriteTag.stringIndex * 4 + 3].position;
Vector3 pox2 = verts[spriteTag.stringIndex * 4 + 2].position;
if (roundingOffset != Vector2.zero)
{
pox1 *= unitsPerPixel;
pox1.x += roundingOffset.x;
pox1.y += roundingOffset.y;
pox2 *= unitsPerPixel;
pox2.x += roundingOffset.x;
pox2.y += roundingOffset.y;
}
else
{
pox1 *= unitsPerPixel;
pox2 *= unitsPerPixel;
}
target.localPosition = pox1;
target.localScale = Vector3.one * (pox2.x - pox1.x) / spriteTag.size.x;
}
}
}
List<UIVertex> vertexList = new List<UIVertex>();
vh.GetUIVertexStream(vertexList);
for (int i = 0; i < spriteTags.Count; i++)
{
if (!spriteTags[i].isVisible) continue;
//UGUIText不支持<quad/>标签,表现为乱码,这里将他的uv全设置为0,清除乱码
for (int m = spriteTags[i].stringIndex * 6; m < spriteTags[i].stringIndex * 6 + 6; m++)
{
UIVertex tempVertex = vertexList[m];
tempVertex.uv0 = Vector2.zero;
tempVertex.uv1 = Vector2.zero;
tempVertex.uv2 = Vector2.zero;
tempVertex.uv3 = Vector2.zero;
tempVertex.color = Color.clear;
vertexList[m] = tempVertex;
}
}
vh.Clear();
vh.AddUIVertexTriangleStream(vertexList);
}
}
}
将脚本挂到Text上,如下图,可以通过调整icon1和icon2的位置来调整图片显示的位置。