zoukankan      html  css  js  c++  java
  • Unity 安卓下DLL热更新一(核心思想)

    大家都知道一谈起热更新的话首选是Ulua这个插件, 其实Unity可以使用dll热更新的,如果你实在不想用Lua来编写逻辑,0.0请下看Dll+AssetBundle如何实现热更新的.让你看完这个文章之后只是认识DLL热更新的方式和概念,掌握热更新的实战框架还需要你自己=。=

    我们通常的做法是编译成的DLL打成AssetBundle文件, Unity通过WWW下载AB文件获取里面DLL.通过反射的方式把里面的C# 组件绑定到GameObject游戏物体上面,这就是DLL热更新的原理. 假设项目采用UGUI系统, 我们来看看通过以上思想编写代码时候遇到的核心问题如下.

    1. 我需要如何编写DLL?
    2. 我的DLL怎么才能获取到UnityEngine命名空间类的引用?
    3. 我的DLL需要如何打成AssetBundle?
    4. 程序下载AssetBundle如何读取里面DLL?
    5. 如何把脚本绑定起来,实现热更新UI?

     

    一、我需要如何编写DLL?

    首先你需要找到Unity几个关键DLL. UnityEngine.dll,UnityEngine.UI.dll为了你编写热更新代码有UnityEngine核心类的引用吧.先创建一个C#3.5版本的类库(点击项目右键->属性->目标框架3.5), 然后引入UnityEngine.dll和UnityEngine.UI.dll的DLL

    image

    创建完工程之后,我们编写一个MyClass继承MonoBehaviour类

    image

    点击启动编译DLL,编译成的DLL可以在项目右键->在文件资源器中打开文件夹->Btn目录->Release和Debug目录找到MyDll.dll(我的是在Realse目录下)  我们把编译好的DLL,拿到Unity里面去打包成AssetBundle文件. Unity默认貌似不允许把后缀名DLL打入AssetBundle,我们修改把MyDll.dll改成MyDll.bytes名字

    image

    把DLL打包成AssetBundle文件代码如下,

    [MenuItem("Assets/Build Android DLL")]
        public static void BuildAssetsAndroidDll()
        {
            Object mainAsset = AssetDatabase.LoadMainAssetAtPath("Assets/Dll/MyDLL.bytes");
            BuildPipeline.BuildAssetBundle(mainAsset, null, Application.dataPath + "\Dll\myassets.android",
                                   BuildAssetBundleOptions.None,BuildTarget.Android);
            if (File.Exists(androidStreamUrl)) 
            {
                File.Delete(androidStreamUrl);
            }   
    
            //拷贝到Stream目录下方便程序下载AB文件
            File.Copy(Application.dataPath + "\Dll\myassets.android", androidStreamUrl);
    
        }

    再来看下我们Unity需要做那些操作,就是新创建一个场景添加一个Text文本即可

    image

    给Android下打包好的AssetBundle文件,放入StreamAssetBundleAssets, 代码会自动帮你复制过去

    image

    Test核心类

    using UnityEngine;
    using System.Collections;
    using System.Reflection;
    using System;
    using System.IO;
    using UnityEngine.UI;
    
    public class Test : MonoBehaviour {
    
    
        public string url;
        public string str;
    
        public Text myAgeText;
    
        public void Awake() 
        {
            Application.logMessageReceived += Application_logMessageReceived;
        }
    
        void Application_logMessageReceived(string condition, string stackTrace, LogType type)
        {
            str += "
    " + condition;
        }
    
        public void OnGUI() 
        {
            GUI.Box(new Rect(0, 0, 800, 800), str);
        }
    
        // Use this for initialization
        IEnumerator Start () {
            yield return new WaitForSeconds(2);
    
            if (Application.platform == RuntimePlatform.WindowsEditor) 
            {
                url = @"file://"+Application.dataPath + "\Dll\myassets.windows";
            }else 
            if(Application.platform == RuntimePlatform.Android)
            {
                url = Application.streamingAssetsPath + "/myassets.android";
            }
            else if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                url = Application.streamingAssetsPath + "/myassets.iphone";
            }
    
            Debug.Log("url: " +  url);
            WWW www = new WWW(url);
    
            yield return www;
    
            if(www.error != null)
            {
                Debug.Log("加载 出错");
            }
    
            if(www.isDone)
            {
                Debug.Log("加载完毕");
                AssetBundle ab = www.assetBundle;
    
                try
                {
                    //先把DLL以TextAsset类型取出来,在把bytes给Assembly.Load方法读取准备进入反射操作
                    Assembly aly = System.Reflection.Assembly.Load(((TextAsset)www.assetBundle.mainAsset).bytes);
    
                    //获取DLL下全部的类型
                    foreach (var i in aly.GetTypes())
                    {
                        //调试代码
                        Debug.Log(i.Name);
                        str += "
    " + i.Name;
    
                        //添加组件到当前GameObject下面
                        Component c = this.gameObject.AddComponent(i);
    
                        //然后类名是MyClass,就把文本引用赋值给MyClass.platefaceText属性.
                        if (i.Name == "MyClass") 
                        {
                            FieldInfo info = c.GetType().GetField("platefaceText");
                            info.SetValue(c, myAgeText);
                        }
                    }
                }
                catch (Exception e) 
                {
                    Debug.Log("加载DLL出错");
                    Debug.Log(e.Message);
                }
            }
        }
    }

    在Windows下查看效果图

    image

    以上只是一个抛砖引玉,希望想使用dll热更新代码的能帮助到你.

    项目下载地址: http://yunpan.cn/cmE4eL5948ghQ  访问密码 df6b

    如果你感兴趣,你可以把你妹妹介绍给我
  • 相关阅读:
    .NET 客户端上传本地excel文件到服务器上,并在客户端显示
    C#实现数字字符串左补齐0的3种方法
    C# 输出pdf文件流在页面上显示
    ASP.NET 将数据生成PDF (二)
    asp.net生成PDF文件 (1)
    stl常用的查找算法
    stl中的transform()注意其与for_each的不同点(有无返回值)
    stl中的for_each() 函数的注意事项
    如何在VMware系统中的ubuntu16.04中建立与win7系统的共享文件夹
    关于linux中用vi新建立一个.c文件无法保存,显示E212错误的时候
  • 原文地址:https://www.cnblogs.com/plateFace/p/4790437.html
Copyright © 2011-2022 走看看