今天遇到一个问题,热更新 UNITY3D Prefab ,prefab上的附加脚本信息丢失(5.X API),然后引发出了有趣的小故事~

BuildPipeline.BuildAssetBundles Build包之后 加载的prefab上脚本丢失?

案例 Prefab

案例 打包脚本

manifest 文件上有脚本的关联信息,猜测是因为 改变了脚本的状态 导致找不到脚本。(一个错误的猜测)

测试(一个错误的测试)

  • 就是打包一个不暴露变量的脚本上去,看看获取ab包的时候能否自动找到本地的脚本
    打包结果
    manifest 文件上 是可以找到两个脚本对应的guid。这里是对应的上的,但是get ab包的时候仍然找不到脚本 ??

勘误

今天晚上重新看了这个问题,发现是由于打包的时候重名文件引起的!这里直接推翻了之前所有的猜测。

勘误测试

文件结构

打包代码如下

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;
using UnityEditor;
using System.Collections;
public class ABBuilder : Editor
{
[MenuItem("Editor/导出ab")]
public static void BudidCurrent()
{
BuildPipeline.BuildAssetBundles("Assets", BuildAssetBundleOptions.None, BuildTarget.iOS);
}
}

附加在prefab之上的测试脚本,本测试目的是测试 testStr 的debug输出是否正常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using UnityEngine;
using System.Collections;
public class showLog : MonoBehaviour
{
public string testStr = "xiaonian";
// Use this for initialization
IEnumerator Start()
{
while (true)
{
yield return new WaitForSeconds(1f);
Debug.Log(testStr);
}
}
// Update is called once per frame
void Update()
{
}
}

AssetBundle的加载如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using UnityEngine;
using System.Collections;
using System.IO;
public class AB : MonoBehaviour
{
IEnumerator Start()
{
yield return new WaitForSeconds(2);
LoadAB();
}
public void LoadAB()
{
var bts = File.ReadAllBytes((Application.dataPath + "/testkeyle"));
var ab = AssetBundle.LoadFromMemory(bts);
var obj = ab.LoadAsset<GameObject>("Cube");
Instantiate(obj);
}
}

测试结果 正常输出

用这段代码演示这个错误的判断

文件结构
生成的manifest信息
测试结果 加载了重名的空预制体

这里可以猜想 是否UNITY3D是遍历生成的信息 找到一个 同名的然后就return出去了 ?

将A文件夹换到最后
这里需要将原来生成的AB包相关信息全部删除,否则只会更新 manifest 文件 !
重新生成的manifest信息与AB包
测试结果 正常的预制体

结论

如果AB包中存在重名的文件 AssetBundle 在加载的时候会顺序查找当前AB包中的文件 找到第一个同名资源就会返回该资源!

就这样结束了吗 新的问题!伴随着解决旧问题 又被发现了 !

too young too native

又是一个演示

我在主场景手动拖放了一个Cube,然后通过AB加载除了一个新的 Cube(Clone)

新的问题~

他俩的材质应该是一样的!但是此处显示居然不一致。通过AB加载出来的prefab材质 拖动数值居然不能改变显示效果。

这个问题我还在查

现在打包到真机看看结果
新的问题~

测试结果

发布到真机发现一切正常 !
我做了一些代码上的修改 然后打包到真机环境