• Unity 代码编译成dll 更新dll实现热更代码


    Unity 代码编译成dll 更新dll实现热更代码

    实现流程

    • 代码编译成DLL
    • DLL打包成AssetBundle
    • 加载AssetBundle
    • 加载代码程序集
    • 获取指定类
    • 使用反射赋值

    C#代码编译成DLL

    • 使用VS创建类库项目

      • 模版->Visual C#-> .NET Framework 3.5-> 类库
      • 名称即为DLL名字(反射的时候要用)
        模版->Visual C#-> .NET Framework 3.5-> 类库
    • 引用两个Unity相关DLL(防止编译报错)

      • 右键项目->添加->引用
        右键项目->添加->引用
      • 在引用管理器窗口->浏览->dll路径
      • UnityEngine.dll默认路径:C:Program FilesUnityEditorDataManaged
      • UnityEngine.UI.dll默认路径:C:Program FilesUnityEditorDataUnityExtensionsUnityGUISystem
        111
    • 编写一个继承MonoBehaviour的简单代码

    using UnityEngine;
    using UnityEngine.UI;
    
    namespace A
    {
        public class Class1 : MonoBehaviour
        {
            public Text text;
    
            int number = 0;
    
            void Update()
            {
                if (Input.GetMouseButtonDown(0))
                {
                    number++;
                    text.text = "鼠标左键按下:" + number;
                }
            }
        }
    }
    
    • 生成DLL
      • 右键项目 生成
      • 在项目的binDebug目录获得DLL

    DLL打包成AssetBundle

    • 把生成的DLL后缀修改为bytes(unity不支持dll后缀打包为AssetBundle)(下图1)
    • 放入项目中 设置AssetBundleName(下图2)
    • 打包代码(放入Editor文件夹)(下图3)
    using UnityEngine;
    using System.Collections;
    using UnityEditor;
    using System.IO;
    
    public class BuildAssetBunble
    {
        [MenuItem("BuildAsset/Bunble")]
        public static void Build()
        {
            BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath, BuildAssetBundleOptions.DeterministicAssetBundle, EditorUserBuildSettings.activeBuildTarget);
    
            AssetDatabase.Refresh();
        }
    }
    
    • 创建StreamingAssets放入AssetBundle文件(下图4)
    • 点击BuildAsset/Bunble按钮(下图5)

    测试代码

    • 创建一个Text游戏对象
    • 新建一个Test代码挂在到Text游戏对象上
    
    using UnityEngine;
    using UnityEngine.UI;
    using System;
    using System.Reflection;
    
    public class Test : MonoBehaviour
    {
        void Start()
        {
            Text text = gameObject.GetComponent<Text>();//获取组建
    
            string path = string.Empty;
    
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                path = Application.streamingAssetsPath + "/a_dll";
            }
            else if (Application.platform == RuntimePlatform.Android)
            {
                path = Application.streamingAssetsPath + "!assets/a_dll";
            }
    
            AssetBundle assetBundle = AssetBundle.LoadFromFile(path);//加载AssetBundle
    
            TextAsset textAsset = assetBundle.LoadAsset<TextAsset>("A");//加载AssetBundle中的A
    
    
            Assembly assembly = Assembly.Load(textAsset.bytes);//加载托管程序集
    
            Type item = assembly.GetType("A.Class1");//获取程序集指定类
    
    
            Component comparer = gameObject.AddComponent(item);//添加到游戏对象上
    
            FieldInfo fieldInfo = comparer.GetType().GetField("text");//使用反射获取实例的字段
    
            fieldInfo.SetValue(comparer, text);//给字段赋值
        }
    }
    
    

    效果如下

    总结

    • 代码图片都有就不上传工程
    • 安卓测试完全没问题
    • IOS不允许使用动态代码所以GG
    • 我这里只是简单实现了 实际上有很多限制
  • 相关阅读:
    xss框架(一)之浏览器通信
    Joomla未授权创建特权用户漏洞和getshell脚本解析
    从零开始写网站登录爆破(一)
    CSRF学习整理
    vue中vue2-google-maps使用谷歌地图的基础操作
    vue中百度地图API的调用
    60秒定时减少
    git操作指令,以及常规git代码操作
    taro taroUi的H5打包后路径/修改为./
    vue enter事件无效,加入native
  • 原文地址:https://www.cnblogs.com/zouqiang/p/10059048.html
Copyright © 2020-2023  润新知