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

    如果你感兴趣,你可以把你妹妹介绍给我
  • 相关阅读:
    HTML5结构
    HTML5新增的非主体元素header元素、footer元素、hgroup元素、adress元素
    CF GYM 100703G Game of numbers
    CF GYM 100703I Endeavor for perfection
    CF GYM 100703K Word order
    CF GYM 100703L Many questions
    CF GYM 100703M It's complicate
    HDU 5313 Bipartite Graph
    CF 560e Gerald and Giant Chess
    POJ 2479 Maximum sum
  • 原文地址:https://www.cnblogs.com/plateFace/p/4790437.html
Copyright © 2011-2022 走看看