Files
5.24BuYu/Assets/Scripts/TMP_SpritePriority.cs
T

91 lines
3.3 KiB
C#
Raw Normal View History

2026-05-18 18:39:11 +08:00
using System.Collections.Generic;
using TMPro;
using UnityEngine;
/// <summary>
/// TMP 图片资源优先渲染器
///
/// 功能:让 TextMeshPro 在渲染字符时,优先查找 SpriteAsset(图片/艺术字),
/// 找不到再 fallback 到 FontAsset(普通字体)。
///
/// 用法:
/// 1. 把此脚本挂到带有 TMP_Text (TextMeshProUGUI / TextMeshPro) 的 GameObject 上
/// 2. 在 Inspector 中把需要优先的 SpriteAsset 拖进 PrioritySpriteAssets 列表
/// (列表顺序即优先级顺序,排第一的最优先)
/// 3. 运行时自动生效;也可手动调用 Apply() 强制刷新
/// </summary>
[AddComponentMenu("UI/TMP Sprite Priority")]
[RequireComponent(typeof(TMP_Text))]
public class TMP_SpritePriority : MonoBehaviour
{
[Header("优先渲染的 SpriteAsset 列表(顺序即优先级,第一个最高)")]
[SerializeField]
private List<TMP_SpriteAsset> prioritySpriteAssets = new List<TMP_SpriteAsset>();
[Header("是否在 Awake 时自动应用")]
[SerializeField]
private bool applyOnAwake = true;
private TMP_Text _tmpText;
private void Awake()
{
_tmpText = GetComponent<TMP_Text>();
if (applyOnAwake)
Apply();
}
/// <summary>
/// 手动触发,将 SpriteAsset 插入 fallback 最前面,实现"Sprite 优先于 Font"渲染
/// </summary>
public void Apply()
{
if (_tmpText == null)
_tmpText = GetComponent<TMP_Text>();
if (_tmpText == null || prioritySpriteAssets == null || prioritySpriteAssets.Count == 0)
return;
// 取第一个作为 TMP_Text.spriteAsset(TMP 解析 <sprite> / unicode 时优先查此处)
_tmpText.spriteAsset = prioritySpriteAssets[0];
// 将剩余 SpriteAsset 插入主 SpriteAsset 的 fallback 链最前端
// TMP 查找 Sprite unicode 的顺序:spriteAsset → spriteAsset.fallbackSpriteAssets[0,1,...] → TMP Settings 默认
if (_tmpText.spriteAsset != null)
{
var fallbacks = _tmpText.spriteAsset.fallbackSpriteAssets;
if (fallbacks == null)
fallbacks = new List<TMP_SpriteAsset>();
// 把列表[1]以后的 asset 依次插入到 fallback 前面(避免重复)
for (int i = prioritySpriteAssets.Count - 1; i >= 1; i--)
{
var asset = prioritySpriteAssets[i];
if (asset == null || fallbacks.Contains(asset)) continue;
fallbacks.Insert(0, asset);
}
_tmpText.spriteAsset.fallbackSpriteAssets = fallbacks;
}
// 强制 TMP 重新解析文本,让新优先级立即生效
_tmpText.SetAllDirty();
_tmpText.ForceMeshUpdate();
Debug.Log($"[TMP_SpritePriority] {gameObject.name} → 首选 SpriteAsset: {_tmpText.spriteAsset?.name},共 {prioritySpriteAssets.Count} 个图片资源已置为最高优先级");
}
/// <summary>
/// 恢复到系统默认(清除手动设置的 spriteAsset,交回 TMP Settings 管理)
/// </summary>
public void Reset()
{
if (_tmpText == null) return;
_tmpText.spriteAsset = null; // null = 使用 TMP Settings 中的默认 SpriteAsset
_tmpText.SetAllDirty();
_tmpText.ForceMeshUpdate();
}
}