Unity将C#脚本转换为DLL,Prefab等文件不丢失引用的方法(转)

Unity将C#脚本转换为DLL,Prefab等文件不丢失引用的方法(转)

unity中Prefab和Scene文件中将使用到的脚本都分配了一个guiid和fileID,来存储和脚本关联关系。如:

m_Script: {fileID: 11500000, guid: 39b76c511f7a56549a8e07bf28e0daae, type: 3}

那么如何将C#脚本转换为DLL,而Prefab等文件又不丢失脚本引用呢?
其实很简单,只需要将guid和fileID,由原先指向cs文件中的类,改为指向DLL文件中的类即可。

guid:指向文件
fileID:指向文件中的类。如果是类名和文件名相同的MonoScript类型组件
那么fileID始终是11500000,具体可以参考这篇文章

剩下就是如何批量、自动化的实现这个过程的问题了。这里借助一个AssetStore上的DLLSwitcher插件

步骤

1.新建空工程,导入DLLSwitcher插件 这个插件的不足是文档很匮乏。按仅有的一个txt说明的那样,将工程设置(Edit->Project Settings->Editor)改成如下所示:

Version Control: Hidden Meta files
Asset Serialization: Force text

2.将需要dll化的unitypackage到导入到工程中
这里以UIWIdgets 1.9.3.unitypackage为例
在这里插入图片描述
3.将CS代码打包成dll(此步骤会存在打包问题,后面会调整)

3.1.这里使用VS新建一个dll工程,直接将UIWidgets目录拷贝到VS工程中。
image
3.2.之后把所有的cs文件include到工程中
image
3.3.将UnityEngine、UnityEditor相关的dll引用添加到工程中,保证目标dll可以正常生成。
image
3.4.(可选)添加UNITY_EDITOR宏到生成配置中
这样生成的dll就会包含Editor相关代码了。中间可能还会遇到一些代码编译不通过的情况,大部分都是由Unity版本相关的宏(如UNITY_5_3_OR_NEWER)引起,添加这些宏到生成配置中即可。
image

4 生成dll文件后,拷贝到Unity工程的Plugins目录下
这时候工程肯定会报错,因为工程中所有的类都存在2份,一份在cs文件中,一份在dll文件中。
image

5 打开DLLSwitcher插件,将生成的dll拖入Dll File后,点击Replace From Src To Dll。
image

观察:替换完成后,可以发现所有的Prefab文件和Scene文件都发生了改写

imageimageimage
在这里插入图片描述
guid:原先对应各个cs文件的guid现在都统一指向dll文件的guid( {guid: 91ea3ce3edb1f944cad92192c2b590d0}
fileID:原先始终为11500000的fileID,变更为新的加密ID,这里的加密生成算法是由"s\0\0\0" + type.Namespace + type.Name的值UTF-8编码后的Byte值经过MD4算法加密后的值。

6 删除Unity工程中的所有cs文件
之后就可以正常运行Scene,Prefab功能正常。
但是!!这个时候如果Build Unity项目,会报错,因为我们之前偷懒,把Editor相关的代码都打包到dll中了,在Editor虽然没问题,打包就会报错了。
image
这时候就需要调整下步骤3

7 将CS代码打包成不含UnityEditor的dll(对应之前的步骤3的调整)
这里使用VS新建一个dll工程,直接将UIWidgets目录拷贝到VS工程中。
image
之后把除Editor相关代码外的所有的cs文件include到工程中
image
将UnityEngine相关的dll引用添加到工程中,保证目标dll可以正常生成,去除对UnityEditor.dll的相关依赖。
image
根据Unity版本将相关的宏(如UNITY_5_3_OR_NEWER)添加到生成配置中。去除UNITY_EDITOR宏。
点击生成如果发现无法生成,一般是部分Editor代码没有Exclude。去除干净Editor代码直到Build Success
image
8 将指向依赖了UnityEditor的dll的Prefab等文件,重新指向不依赖UnityEditor的dll
可惜的是,这个插件不含有dll重新指向的功能,那只能在它的基础上自己写一个了方法了。链接
含有Editor依赖的dll设置成只在Editor下使用。
不含有Editor依赖的dll设置成在其他环境下使用。

imageimage
在这里插入图片描述
平时开发的时候,将prefab等关联从src替换到含有Editor依赖的dll上,build出包的时候,再将关联移到不含有Editor依赖的dll上。

写在最后
当然还有一种一劳永逸的方法,就是在dll构建的时候完全去除Editor相关的代码,并且在Unity Project中只保留Editor文件夹下相关的cs文件。这里还需要特别处理的是:有部分插件会使用UNITY_EDITOR宏,导致这部分代码需要手动分离出来放到Editor文件夹下处理。
至于选择哪种方法,就是见仁见智了。本人更倾向于使用这种方法,毕竟一个项目在打包和开发的时候来回切换dll的关联会是一件很麻烦的事情。分离出Editor代码,虽然前期会做很多工作,但是后期就不存在切换dll关联的诸多事宜。

版权声明:本文为转载文章 ,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
转载链接:https://www.pianshen.com/article/1647348773/

这里分享一下部分手写核心代码```
获取localID

 static int GetLocalID(Object obj)
    {
        PropertyInfo info = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
        SerializedObject sObj = new SerializedObject(obj);
        info.SetValue(sObj, InspectorMode.Debug, null);
        SerializedProperty localIdProp = sObj.FindProperty("m_LocalIdentfierInFile");
        return localIdProp.intValue;
    }

``
获取特定目录下面的localID和guid

 public static void GetInfo()
    { //获取特定目录guid local信息 这里以dll为例子
        var dDll = new Dictionary<string, string>();
        var monoBehaviours = Resources.FindObjectsOfTypeAll<MonoScript>();
        foreach (var m in monoBehaviours)
        {
            if (m == null || m.GetClass() == null)
                continue;
            var path = AssetDatabase.GetAssetPath(m);
            if (path.StartsWith(DLLPath))//dll所在目录 过滤条件等
            {
                var localID = GetLocalID(m);
                var GUID = AssetDatabase.AssetPathToGUID(path);
                dDll.Add(m.GetClass().FullName, $"  m_Script: {{fileID:{localID}, guid: {GUID}, type:3}}");
            }
        }
        //Debug.Log(dDll); 
    }


  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值