如何正确使用AssetBundles预制体?加载出现缩放、脚本依赖异常
AssetBundle加载后对象缩放异常、脚本引用丢失解决方案
问题现象
开发角色收集金币类轻量游戏时,将场景内背景、玩家、地形等资源制作成prefab打入AssetBundle包,加载实例化后出现两个异常:
- Inspector面板中对象的尺寸、Transform参数和原prefab完全一致,但运行时实际渲染尺寸远大于原prefab,玩家角色尺寸达到原尺寸的10倍,所有加载资源尺寸匹配当前加载界面大小
- 加载出的对象上的脚本依赖丢失,必须运行时重新绑定才能正常用摇杆控制角色
原加载脚本如下:
public class LoadAssetBundles : MonoBehaviour { AssetBundle loadedAssetBundle; public string path; public string assetName; void Start() { LoadAssetBundle(path); InstantiateObjectFromBundle(assetName); } void LoadAssetBundle(string bundleUrl) { loadedAssetBundle = AssetBundle.LoadFromFile(bundleUrl); } void InstantiateObjectFromBundle(string assetName) { var prefab = loadedAssetBundle.LoadAsset(assetName); Instantiate(prefab); } }
问题参考截图:


根因分析
两个问题分别由AssetBundle使用中的两个常见疏漏导致:
- 尺寸异常放大:加载逻辑执行时当前处于加载界面场景,加载界面的Canvas挂载了
Canvas Scaler组件并开启了Scale With Screen Size适配模式,当前适配计算出的Canvas缩放值恰好为10。调用无参Instantiate(prefab)时,如果prefab带有RectTransform组件(包括被误存为UGUI子对象的2D游戏对象),Unity会默认将实例挂载到当前场景第一个活跃Canvas下。Inspector中显示的是对象的localScale(和原prefab一致为(1,1,1)),但实际渲染使用的全局缩放lossyScale会继承父级Canvas的缩放值,最终表现为对象被放大10倍、尺寸匹配加载界面。 - 脚本引用丢失:打包AssetBundle时,未将prefab依赖的摇杆组件、对应脚本、公共资源打入包内或提前加载依赖包;或是prefab上脚本的字段引用指向了Hierarchy中的场景实例而非Project窗口的资产,导致加载后引用断裂,必须手动重新绑定才能正常工作。
修复方案
修复尺寸异常
- 实例化时显式指定正确的父节点,禁止Unity自动将对象挂载到加载界面Canvas下。非UI游戏对象指定到游戏场景根节点或专门的游戏内容挂载节点;UGUI对象指定到游戏主Canvas下的对应节点,实例化时传入
worldPositionStays = false参数避免继承异常缩放。修改后的实例化代码如下:
// Inspector中拖拽游戏场景的内容根节点/游戏主Canvas节点给该字段赋值 public Transform targetParent; void InstantiateObjectFromBundle(string assetName) { var prefab = loadedAssetBundle.LoadAsset(assetName); // 普通2D/3D非UI对象用以下写法 // Instantiate(prefab, targetParent); // UGUI对象用以下写法,强制不保留世界坐标偏移、缩放 Instantiate(prefab, targetParent, false); }
- 打包前检查prefab配置:非UI的游戏角色、地形、背景对象不要存为Canvas的子物体,确保普通2D/3D对象挂载的是
Transform组件而非RectTransform,避免被Unity识别为UI元素自动挂载到Canvas。 - 如果需要在加载界面场景提前加载资源,可先将加载出的prefab存在内存变量中,等游戏场景加载完成、加载界面完全卸载后再执行实例化,避免被加载界面的Canvas缩放影响。
修复脚本引用丢失
- 打包AssetBundle时,使用AssetBundle构建工具自动收集所有依赖项,将prefab引用到的脚本、摇杆组件、材质、精灵等公共资源单独打包为依赖包,加载主资源包前先加载所有依赖包,即可避免引用丢失。
- 检查prefab上的脚本赋值:所有Inspector中拖拽的引用对象必须是Project窗口内的资产,不能指向Hierarchy面板中的场景实例,场景实例的引用无法被AssetBundle序列化保存,必须在场景加载完成后通过代码动态赋值。
内容的提问来源于stack exchange,提问作者Vitaliy Radchuk
相关产品推荐
相关产品推荐

