Unity dll 热更新 基础框架

来源:互联网 发布:淘宝网包包新款 编辑:程序博客网 时间:2024/05/22 23:02

昨晚上有了dll 热更新的想法,今天做了一天的实验,也遇到些坑,这里总结下

工作环境: U3D5.3.2 + vs2010 +mono

下面要模拟的是一个登陆环境,点击按钮,就加载一个iGameObjec的Item,  Item 上得到更新的文本内容。具体如下图

http://download.csdn.net/detail/pdw_jsp/9436889 源码下载

点击打开链接 完整源码

-LoginPanel(动态加载脚本LoginUIc.cs)

   -itemRoot

        -Item(动态加载的Item.cs) 并加载动态的脚本


1> 程序集管理

 

using UnityEngine;  using System.Collections;  using System;  public class AssemblyLoader : MonoBehaviour {private static readonly string DLL_URL ="file:///" + Application.dataPath+"/Plugins/ExtDll.assetbundle";System.Reflection.Assembly assembly;void Awake(){StartCoroutine(loadDllScript()); }private IEnumerator loadDllScript()  {  WWW www = new WWW(DLL_URL);  yield return www;  AssetBundle bundle = www.assetBundle;  TextAsset asset = bundle.LoadAsset("ExtDll",typeof(TextAsset)) as TextAsset;  assembly = System.Reflection.Assembly.Load(asset.bytes);  yield return null;if (assembly != null) {Type type = assembly.GetType ("DllManager");Component com = gameObject.AddComponent(type);System.Reflection.MethodInfo methodInfo = type.GetMethod ("InitAssembly");object[] obj = new object[]{assembly};methodInfo.Invoke (com, obj); //反射调用DllManager Debug.Log ("dll load suc");}}  }

2> Dll管理与加载 

using UnityEngine;  using System.Collections;  using System;  public class DllManager:MonoBehaviour{  public static DllManager Instance;public System.Reflection.Assembly assembly;void Awake(){Instance = this;}public void InitAssembly(System.Reflection.Assembly assembly){this.assembly = assembly;        AddCompotent(gameObject, "WndManager");}public Component AddCompotent(GameObject prefab, string compotentName){
               //只有android进行dll热更处理if (Application.platform == RuntimePlatform.Android) {if (assembly != null) {Type type = assembly.GetType (compotentName);if (prefab != null) {Debug.Log ("---------->add momo suc");prefab.AddComponent(type);}return null;}} else {Component com = prefab.GetComponent (compotentName);if(com == null){Type type = Type.GetType (compotentName); prefab.AddComponent (type);}return com;}return null;}}  


3> 逻辑代码和UI的实现 

这里窗口管理器只是一个模拟加载LoginUI的过程,具体的会有自己的一套窗口管理~~勿喷

using UnityEngine;using System.Collections;public class WndManager : MonoBehaviour {// Use this for initializationvoid Start () {DllManager.Instance.AddCompotent (gameObject, "LoginUI");}}

下面来看看LoginUI做了些什么

using UnityEngine;using System.Collections;using UnityEngine.UI;public class LoginUI : Momo {string msg;public Text text;    public Button btn;public GameObject itemRoot;protected override void Awake (){base.Awake ();}protected override void InitPanelCompotent (){base.InitPanelCompotent ();text = transform.FindChild ("Text").GetComponent<Text>();text.text = "andorid modify ";btn = transform.FindChild ("Button").GetComponent<Button>();btn.onClick.AddListener(OnClick);itemRoot = transform.FindChild ("itemRoot").gameObject;Debug.Log ("LoginUI InitPanelCompotent");}public void OnClick(){LoginManager.Instance.data = new Data (text.text, text.text);msg = "name = "+ LoginManager.Instance.data.name+" , password = " + LoginManager.Instance.data.password;Object res = Resources.Load ("Item");GameObject item = GameObject.Instantiate (res, Vector3.zero, Quaternion.identity) as GameObject;item.transform.parent = itemRoot.transform;item.transform.localPosition = Vector3.zero;DllManager.Instance.AddCompotent(item, "Item");}protected override void InitPanelData (){base.InitPanelData ();Debug.Log ("LoginUI InitPanelData");AddFun ();}protected void AddFun(){Debug.Log ("this is add fun");}void OnGUI(){GUI.Label(new Rect(0, 0, Screen.width, Screen.height), msg);}}

LoignUI 继承了Momo的一个类。这个类定义好了一个初始化的流程,也就是初始化panel 数据, 加载panel组件,所有的UI必须这样来完成(其实lua也有这个过程,不停的find,而这里我们可以展望一个工具,这个工具会帮我们初始化这部分工作。)

using UnityEngine;using System.Collections;public class Momo : MonoBehaviour {protected virtual void Awake(){InitPanelCompotent ();InitPanelData ();}protected virtual void InitPanelCompotent(){Debug.Log ("moo InitPanelCompotent");}protected virtual void InitPanelData(){Debug.Log ("moo InitPanelData");}}

其他脚本略(下载后面的脚本集合,因为后面还有更重要的要写,这篇又会太长)

4> 打包dll+打包Assetbundle

  ok 完成了上诉的代码编写工作,现在就进行dll的生成

  

外部库引入的时候注意UnityEngine.UI 的路径是不同于UnityEngine.dll的。自己在安装目录下搜就知道了。

这里需要注意的是:.net必须选为3.5 否则无法进行,低于3.5的unity的库文件找不到,高了的unity运行会报错,所以必须是3.5



然后点击生成就可以生成我们需要的dll了,然后去你工程目录下的 bin/debug/ExtDll .dll工程

然后将这个ExtDll.dll放到unity中的Plugin下并改名为ExtDll.bytes 然后打包成AssetBundle. 注意Assetbundle的平台设置

ok。打出来的ExtDll.assetbundle 就安静的躺在了Plugin下面了。


5>测试

点击button 如果出现如下的表示成功了



可能遇到的坑~~~不过在我这边都是被解决了

限制1:在Android手机里动态加载dll不能使用Assembly.LoadFile(string path),只能使用Assembly.Load(byte[] rawAssembly)这个接口,所以要自己想办法先读出来。


限制2:动态加载的脚本不能在编辑器里挂在prefab上。


限制3:如果脚本在动态dll里,调用AddComponent()挂此脚本上prefab上时不能使用AddComponent(“SomeScript”)的方式调用,要用AddComponent(Type.GetType(“SomeScript”))。


限制4:在动态dll里使用[RequireComponent(typeof(SomeScript))]无效,所以不能使用。


====================================================================================================================================补充一下vs2010 中dll 的生成步骤

新建项目

已安装模板(这里选择C# /Windows/类库)点击确定

删掉默认创建的那个文件,拷贝UnityEngine.dll 和 你需要的**.cs文件到工程目录中

右键添加 / 添加现有项 把cs文件导入到工程

右键添加 /  添加引用把 UnityEngine.dll 文件加入到类库中

最后右键生成,如果没有报错那么在你的debug下就有你刚刚生成的***.dll文件


   


2 0