You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中SpriteLibrary类编辑问题求助:自定义方法丢失且无法修改

问题描述

我对项目的运行机制和代码编译逻辑不太理解,不清楚当前问题的成因。我的代码需要从SpriteLibrary中获取数据,因为不知道正确的获取方式,我直接在SpriteLibrary类内部写了以下方法:

public void CopyLibraryFrom(SpriteLibrary sourceLibrary)
{
    foreach (var sourceCategory in sourceLibrary.m_Library)
    {
        var targetCategory = new SpriteLibCategory
        {
            name = sourceCategory.name,
            categoryList = new List<SpriteCategoryEntry>()
        };

        foreach (var sourceEntry in sourceCategory.categoryList)
        {
            var targetEntry = new SpriteCategoryEntry
            {
                name = sourceEntry.name,
                sprite = sourceEntry.sprite
            };

            targetCategory.categoryList.Add(targetEntry);
        }

        m_Library.Add(targetCategory);
    }
    CacheOverrides();
    RefreshSpriteResolvers();
}

遇到的问题:

  • Visual Studio会自动删除我添加的这个方法和所有修改,得多次取消自动删除才能保存。我猜测是Unity自动更新SpriteLibrary并重置为默认状态导致的。想问下能不能正常编辑保存SpriteLibrary?还是我的操作方式错了?
  • 一个月没打开Unity后,再次运行报错:"SpriteLibrary中不存在CopyLibraryFrom方法"。现在打开SpriteLibrary显示是反编译的,完全没法编辑。我知道自己操作有误,但不知道正确做法是什么,该怎么修复当前问题?现在该怎么编辑它,或者有没有其他方法实现需求并正常运行?

解决方案

为什么不能直接编辑SpriteLibrary?

SpriteLibrary是Unity官方提供的内置类(属于Sprite Library Package或UI Toolkit模块),你看到的可编辑代码是Visual Studio自动生成的反编译元数据视图,直接修改这类内置类的代码完全不可行:

  • Unity每次编译、刷新项目或重启时,都会重新加载官方编译好的程序集,你的修改会被自动覆盖,这就是Visual Studio自动删除代码的原因。
  • 即使临时保存了修改,一旦Unity重新编译,内置程序集就会被还原,你的自定义方法会直接消失,导致后续报错。

正确实现方式:扩展方法

不要修改内置类,用C#的扩展方法实现需求,既不会破坏Unity内置代码,也能达到同样效果:

using UnityEngine;
using System.Collections.Generic;
using System.Reflection;
// 根据你项目中SpriteLibrary的实际命名空间调整,比如UnityEngine.Experimental.U2D.Animation或UnityEngine.UIToolkit
using UnityEngine.Experimental.U2D.Animation;

public static class SpriteLibraryExtensions
{
    public static void CopyLibraryFrom(this SpriteLibrary targetLibrary, SpriteLibrary sourceLibrary)
    {
        // 通过反射获取私有字段m_Library
        var libraryField = typeof(SpriteLibrary).GetField("m_Library", BindingFlags.NonPublic | BindingFlags.Instance);
        if (libraryField == null) return;
        
        var targetLibraryList = libraryField.GetValue(targetLibrary) as List<SpriteLibCategory>;
        var sourceLibraryList = libraryField.GetValue(sourceLibrary) as List<SpriteLibCategory>;
        
        if (targetLibraryList == null || sourceLibraryList == null) return;
        
        // 先清空目标库,避免重复添加
        targetLibraryList.Clear();
        
        foreach (var sourceCategory in sourceLibraryList)
        {
            var targetCategory = new SpriteLibCategory
            {
                name = sourceCategory.name,
                categoryList = new List<SpriteCategoryEntry>()
            };

            foreach (var sourceEntry in sourceCategory.categoryList)
            {
                var targetEntry = new SpriteCategoryEntry
                {
                    name = sourceEntry.name,
                    sprite = sourceEntry.sprite
                };

                targetCategory.categoryList.Add(targetEntry);
            }

            targetLibraryList.Add(targetCategory);
        }
        
        // 通过反射调用内置私有方法
        var cacheOverridesMethod = typeof(SpriteLibrary).GetMethod("CacheOverrides", BindingFlags.NonPublic | BindingFlags.Instance);
        cacheOverridesMethod?.Invoke(targetLibrary, null);
        
        var refreshResolversMethod = typeof(SpriteLibrary).GetMethod("RefreshSpriteResolvers", BindingFlags.NonPublic | BindingFlags.Instance);
        refreshResolversMethod?.Invoke(targetLibrary, null);
    }
}

使用方式

在业务代码中直接像调用内置方法一样使用:

SpriteLibrary targetLib = GetComponent<SpriteLibrary>();
SpriteLibrary sourceLib = ...; // 获取源SpriteLibrary实例

targetLib.CopyLibraryFrom(sourceLib);

修复当前报错的步骤

  1. 彻底删除之前对SpriteLibrary内置类的所有修改,确保Unity内置程序集未被篡改。
  2. 创建上述SpriteLibraryExtensions类,放在项目Assets目录下的任意脚本文件夹中。
  3. 重启Unity和Visual Studio,让项目重新编译。
  4. 将原来调用CopyLibraryFrom的代码改为使用扩展方法的形式,即可解决报错。

额外注意事项

  • 如果SpriteLibCategory或SpriteCategoryEntry是Unity内部类无法直接实例化,可以改用反射复制字段值。
  • 务必确认SpriteLibrary的正确命名空间,不同Unity版本的命名空间可能不同,需根据项目实际情况调整。

内容的提问来源于stack exchange,提问作者Дмитрий Титов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:18:10