Unity 动态修改图集内容

这个代码示例展示了在Unity中如何修改图集并填补指定区域,以及如何进行纹理压缩。通过`AmendAtlas`函数,可以更新图集中的指定部分,并用新的纹理数据填充。同时,`ReSetTextureSize`函数用于调整纹理尺寸。最后,`writeCaptureDataToFile`将处理后的纹理保存为JPEG文件。这是一个关于Unity图形处理和资源管理的实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先上代码

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System;

public class Test3 : MonoBehaviour
{   

    public RawImage image;
    public Texture2D te;
    public Texture2D texture;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            image.texture = AmendAtlas(new UnityEngine.Vector2(0,1536),new UnityEngine.Vector2(512,512),te,texture);
        }
    }
    /// <summary>
    /// 修改图集
    /// </summary>
    public Texture2D AmendAtlas(UnityEngine.Vector2 _修改图片的起始点, UnityEngine.Vector2 _修改图集的范围,Texture2D _图集,Texture2D _要添加的图片)
    {
        Color[] colors = _图集.GetPixels();
        Texture2D texture2D = new Texture2D(_图集.width, _图集.height);
        texture2D.SetPixels(colors);
        texture2D.SetPixels((int)_修改图片的起始点.x, (int)_修改图片的起始点.y, (int)_修改图集的范围.x, (int)_修改图集的范围.y, _要添加的图片.GetPixels());
        texture2D.Apply();

        return texture2D;
    }
   
    /// <summary>
    /// 图片压缩
    /// </summary>
    /// <param name="tex"></param>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <returns></returns>
    public Texture2D ReSetTextureSize(Texture2D tex, int width, int height)
    {
        var rendTex = new RenderTexture(width, height, 24, RenderTextureFormat.ARGB32);
        rendTex.Create();
        Graphics.SetRenderTarget(rendTex);
        GL.PushMatrix();
        GL.Clear(true, true, Color.clear);
        GL.PopMatrix();
        var mat = new Material(Shader.Find("Unlit/Transparent"));
        mat.mainTexture = tex;
        Graphics.SetRenderTarget(rendTex);
        GL.PushMatrix();
        GL.LoadOrtho();
        mat.SetPass(0);
        GL.Begin(GL.QUADS);
        GL.TexCoord2(0, 0);
        GL.Vertex3(0, 0, 0);
        GL.TexCoord2(0, 1);
        GL.Vertex3(0, 1, 0);
        GL.TexCoord2(1, 1);
        GL.Vertex3(1, 1, 0);
        GL.TexCoord2(1, 0);
        GL.Vertex3(1, 0, 0);
        GL.End();
        GL.PopMatrix();
        var finalTex = new Texture2D(rendTex.width, rendTex.height, TextureFormat.ARGB32, false);
        RenderTexture.active = rendTex;
        finalTex.ReadPixels(new Rect(0, 0, finalTex.width, finalTex.height), 0, 0);
        finalTex.Apply();
        return finalTex;
    }
   

    public void writeCaptureDataToFile(Texture2D texture, string dataPath, string filename)
    {
        string path_full =Path.Combine(dataPath,filename+".jpg");
 
        // 存入jpg文件
        StartCoroutine(saveTexture2DtoFile(texture, path_full));
    }
 
    // 保存图片到指定目录
    private IEnumerator saveTexture2DtoFile(Texture2D texture, string path, Action<object> callback=null)
    {
        //等待渲染线程结束  
        yield return new WaitForEndOfFrame();
 
        byte[] textureData = texture.EncodeToJPG();
        System.IO.File.WriteAllBytes(path, textureData);
 
        callback?.Invoke(null);
        Debug.Log("图片文件写入完毕:" + path);
    }
}

在这里插入图片描述
这图集大小为 1024 * 2048
修改红色框住的部分 并填补
该区域大小为 512 * 512
起始点为该区域的左下角 位置为 (0,1536)

填入数据
然后运行代码
得到下面的结果

在这里插入图片描述

Over

<think>我们正在处理关于Unity中使用TextMeshPro打包Sprite图集的问题。根据用户的问题,我们需要将Sprite图集与TextMeshPro结合使用。TextMeshPro使用自己的Sprite图集系统(称为Sprite Asset),它允许在文本中嵌入图标。根据引用[1],我们看到了如何通过代码从SpriteAtlas中加载图片到Image组件。但TextMeshPro需要的是Sprite Asset,而不是普通的Sprite或SpriteAtlas。引用[2]和[3]提供了关于TextMeshPro的信息,特别是引用[3]提到了如何从AssetBundle加载SpriteAsset。这为我们提供了线索:TextMeshPro使用Sprite Asset资源,并且我们可以通过AssetBundle加载它。因此,打包TextMeshPro的Sprite图集(即创建Sprite Asset)并加载使用,需要以下步骤:1.创建SpriteAsset:-首先,我们需要准备一个包含所有精灵的纹理图集(通常是一个PNG文件)和一个对应每个精灵位置的文本文件(记录精灵的名称、位置、大小等)。这个文本文件可以是Unity的Sprite Editor导出的.spriteatlas文件,但TextMeshPro需要的是它自己的格式。-实际上,TextMeshPro提供了创建SpriteAsset的工具。我们可以通过Unity编辑器菜单创建。2.打包SpriteAsset到AssetBundle:-将创建好的Sprite Asset打包到AssetBundle中,以便动态加载。3.运行时加载Sprite Asset:-从AssetBundle中加载Sprite Asset,然后将其应用到TextMeshPro组件上(如TMP_Text或TMP_SubMeshUI)。具体步骤:步骤1:创建SpriteAsset-准备一个精灵纹理(例如:一个包含多个图标的PNG文件)和每个图标的UV信息(通常通过Unity的SpriteEditor切割后,每个Sprite都有一个名称)。-在Project窗口中,选择这个纹理(或者包含多个Sprite的纹理图集),然后右键选择“Create> TextMeshPro> Sprite Asset”。-这将创建一个新的Sprite Asset资源(.asset文件),其中包含了纹理引用和每个Sprite的glyph信息。步骤2:打包到AssetBundle-在Unity编辑器中,选择我们创建的SpriteAsset资源。-在Inspector窗口中,找到AssetBundle设置(通常在底部),可以新建一个AssetBundle(例如:spriteassets)并分配,然后将其标记为需要打包。-使用Unity的BuildPipeline构建AssetBundle。步骤3:运行时加载-使用AssetBundle加载系统(如AssetBundle.LoadFromFile或UnityWebRequestAssetBundle)加载包含Sprite Asset的AssetBundle。-从AssetBundle中加载具体的SpriteAsset资源(使用名称或路径)。-将加载到的SpriteAsset赋给TMP_Text组件的spriteAsset属性(如引用[3]所示)。注意:引用[3]中展示了Lua伪代码,但我们可以用C#实现类似逻辑。示例代码(C#):假设我们已经从AssetBundle中加载了一个SpriteAsset,命名为“emojidata”:```csharpusingUnityEngine;using TMPro;using System.Collections; publicclass LoadSpriteAsset: MonoBehaviour{publicTMP_TexttextComponent; //你的TMP文本组件IEnumerator Start(){//加载AssetBundlestringassetBundlePath =Application.streamingAssetsPath +"/ui/spriteassets/emojidata";AssetBundleCreateRequest request= AssetBundle.LoadFromFileAsync(assetBundlePath);yieldreturn request;AssetBundlebundle =request.assetBundle;if(bundle ==null){Debug.LogError("Failedto loadAssetBundle!");yield break;}//加载SpriteAssetAssetBundleRequestassetRequest =bundle.LoadAssetAsync<TMP_SpriteAsset>("emojidata");yieldreturn assetRequest;TMP_SpriteAssetspriteAsset= assetRequest.asset asTMP_SpriteAsset;if(spriteAsset== null){Debug.LogError("Failed toload Sprite Asset!");bundle.Unload(false);yield break;}//设置给TMP文本组件textComponent.spriteAsset =spriteAsset;//注意:如果文本中有子网格(比如富文本中的表情),也需要设置子网格的spriteAsset(如引用[3]所示)//但通常,TMP_Text组件会处理子网格,我们只需要设置主组件的spriteAsset即可。不过,如果遇到子网格不显示,可以尝试手动设置子网格的spriteAsset。//以下是设置所有子网格的代码(可选):var subMeshes= textComponent.GetComponentsInChildren<TMP_SubMeshUI>(true);foreach(varsubMeshin subMeshes){subMesh.spriteAsset =spriteAsset;}//卸载AssetBundle,但保留加载的资源(因为spriteAsset已经被引用)bundle.Unload(false);} }```注意:上面的代码是异步加载,也可以使用同步方法,但在实际项目中异步更常见。另外,如果不想使用AssetBundle,也可以将SpriteAsset放在Resources文件夹下,使用Resources.Load加载(但这种方式在大型项目中不推荐,因为Resources文件夹有性能问题)。总结:1.创建SpriteAsset:通过纹理创建TextMeshPro的SpriteAsset。2.打包:将SpriteAsset打包到AssetBundle。3.加载:运行时从AssetBundle加载Sprite Asset并设置给TMP_Text组件。这样,我们就可以在TextMeshPro文本中使用这个图集中的精灵了。在文本中,使用<sprite name="精灵名称">来嵌入精灵。相关问题:1.如何创建TextMeshPro的SpriteAsset?2.如何将Sprite Asset打包到AssetBundle?3.如何在运行时动态加载SpriteAsset并应用到TextMeshPro文本?4.在TextMeshPro文本中如何引用SpriteAsset中的单个精灵?5.如何处理TextMeshPro子网格的SpriteAsset设置?</think>### Unity TextMeshPro Sprite 图集打包方法 在 Unity 中为 TextMeshPro (TMP) 打包 Sprite 图集需要以下步骤: #### 1. **创建 Sprite Asset** - 准备精灵图集 PNG 文件(需开启 **Read/Write Enabled**) - 在 Project 窗口右键选择:`Create > TextMeshPro > Sprite Asset` - 自动生成 `.spriteatlas` 文件和 `.asset` 资源文件 - 在 Inspector 中配置: ```text Sprite Atlas: 选择图集纹理 Material Preset: 选择 TMP 默认材质 ``` #### 2. **配置 Sprite 信息** - 在生成的 Sprite Asset 文件中: - 设置每个精灵的 **ID** 和 **Unicode 码点**(如 `U+E000`) - 调整精灵的 **UV 坐标**、**尺寸** 和 **偏移量** - 示例配置: ```csharp // 伪代码:精灵属性结构 public struct TMP_SpriteGlyph { public int index; // 精灵索引 public Rect glyphRect; // UV 矩形 public Vector2 scale; // 缩放比例 } ``` #### 3. **打包到 AssetBundle** ```csharp using UnityEditor; using TMPro; public class SpriteAssetPacker { [MenuItem("Assets/Build TMP Sprite AssetBundle")] public static void BuildAssetBundle() { // 选择要打包的 Sprite Asset TMP_SpriteAsset spriteAsset = Selection.activeObject as TMP_SpriteAsset; // 配置 AssetBundle AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(spriteAsset)) .SetAssetBundleNameAndVariant("tmpsprites", ""); // 构建 AssetBundle BuildPipeline.BuildAssetBundles( "Assets/AssetBundles", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows ); } } ``` #### 4. **运行时动态加载**(参考引用[3]) ```csharp using TMPro; using UnityEngine; public class LoadSpriteAsset : MonoBehaviour { public TMP_Text targetText; IEnumerator Start() { // 从 AssetBundle 加载 AssetBundleRequest request = AssetBundle.LoadFromFile("AssetBundles/tmpsprites") .LoadAssetAsync<TMP_SpriteAsset>("EmojiData"); yield return request; // 应用到文本组件 targetText.spriteAsset = request.asset as TMP_SpriteAsset; // 更新子网格(关键步骤) foreach (var subMesh in targetText.GetComponentsInChildren<TMP_SubMeshUI>(true)) { subMesh.spriteAsset = targetText.spriteAsset; } } } ``` #### 5. **在文本中使用精灵** ```html <!-- 在 TMP 文本框中输入 --> Hello <sprite name="smile_icon"> World! <!-- 或通过 Unicode 引用 --> Character: <sprite index=0> ``` #### ⚠️ 注意事项 1. **图集尺寸限制**:最大 4096×4096 像素,需开启 **Generate Mip Maps** 2. **材质同步**:修改图集后需重新生成材质(通过 `Sprite Asset Editor > Update Material`) 3. **动态更新**:修改精灵后调用 `targetText.SetAllDirty()` 刷新显示 4. **跨平台兼容**:iOS/Android 需启用 **ASTC** 压缩格式 > 完整文档参考:[TextMesh Pro Sprite Assets](https://docs.unity3d.com/Packages/com.unity.textmeshpro@3.0/manual/SpriteAssets.html)[^2] --- ### 相关问题 1. **如何解决 TextMeshPro 精灵显示为粉红色的问题?** *(材质/着色器配置错误排查)* 2. **TextMeshPro 精灵图集与普通 SpriteAtlas 有何区别?** *(TMP 专用数据结构 vs Unity 通用图集)* 3. **如何通过脚本动态添加新精灵到已打包的 Sprite Asset?** *(运行时修改 SpriteGlyphTable 的方法)* 4. **TextMeshPro 精灵图集在多语言项目中的最佳实践是什么?** *(本地化方案与图集拆分策略)* [^1]: Unity SpriteAtlas 加载示例 [^2]: TextMesh Pro 官方文档 [^3]: AssetBundle 加载 Sprite Asset 的伪代码实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值