Unity Editor如何通过代码访问已切片纹理内的子Sprite对象
Unity编辑器脚本获取已切片PNG下Sprite资源返回null问题
需求背景
- 需要在自定义Editor工具中,无交互访问当前选中的、已在Sprite Editor完成切片的PNG资源下的所有Sprite子资源
- 场景示例:自定义GUIEditor已可识别当前选中的
Druid_jump纹理,需要直接获取从Druid_Jump_0_00到Druid_Jump_3_03的所有Sprite对象,用于配置4组动画剪辑 - 参考截图:

问题复现代码
List<Texture2D> textures = new List<Texture2D>(Selection.GetFiltered<Texture2D>(SelectionMode.Unfiltered)); foreach (Texture texture in textures) { if (texture != null) { string path = AssetDatabase.GetAssetPath(texture); string containingFolder = null; if (string.IsNullOrEmpty(containingFolder)) { containingFolder = path.Remove(path.LastIndexOf('/')); } var importer = AssetImporter.GetAtPath(path) as TextureImporter; List<Sprite> currentFrames = new List<Sprite>(); int index = 0; foreach (SpriteMetaData spriteMetaData in importer.spritesheet) { string[] slice = spriteMetaData.name.Split('_'); if (slice[2] != index.ToString()) { //CreateAnimation(currentFrames.Count, currentFrames); currentFrames = new List<Sprite>(); index++; } // 代码执行到此处前均正常,需要获取Sprite类型对象完成动画创建 Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>($"{containingFolder}/{spriteMetaData.name}"); //currentFrames.Add(sprite); Debug.Log(sprite.name); } } }
问题现象
代码执行到获取Sprite实例的逻辑前均可正常运行,遍历importer.spritesheet可正确返回所有切片的Sprite名称,但用于加载单个Sprite的代码AssetDatabase.LoadAssetAtPath<Sprite>($"{containingFolder}/{spriteMetaData.name}")始终返回null,无法拿到Sprite类型对象完成后续动画创建逻辑。
解决方案
返回null的核心原因是加载路径错误。Sprite Editor切分生成的Sprite不是存放在资源同级目录下的独立文件,是挂载在原PNG纹理下的子资源,拼接的{containingFolder}/{spriteMetaData.name}路径不存在对应资源,自然返回null。
两种可直接落地的修复方式:
- 方式1:批量加载所有子Sprite做映射(推荐,性能更好)
在遍历spritesheet前一次性加载当前PNG下的所有Sprite,按名称建立字典,循环内直接匹配即可:
// 遍历spritesheet前执行,加载当前纹理下所有Sprite建立映射 Dictionary<string, Sprite> spriteLookup = AssetDatabase.LoadAllAssetsAtPath(path) .OfType<Sprite>() .ToDictionary(s => s.name, s => s); foreach (SpriteMetaData spriteMetaData in importer.spritesheet) { // 其余原有分组逻辑不变 Sprite sprite = spriteLookup[spriteMetaData.name]; currentFrames.Add(sprite); Debug.Log(sprite.name); }
- 方式2:按子资源路径格式加载
Unity加载子资源的路径格式为主资源路径/子资源名称,不需要拼接文件夹路径,直接用PNG本身的asset路径拼接Sprite名即可:
// 替换原有加载Sprite的代码 Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>($"{path}/{spriteMetaData.name}");
额外注意:现有分组逻辑存在遗漏,切换分组时注释的CreateAnimation方法不会触发,最后一组动画帧也不会走到创建分支,需要补全对应处理。
内容的提问来源于stack exchange,提问作者James D
相关产品推荐
相关产品推荐

