Unity dll 热更新 基础框架

昨晚上有了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 initialization
	void 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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值