• Unity 3D模型展示框架篇之ILRuntime整合与应用


    系列文章目录

    Unity 3D模型展示框架篇之项目整理
    Unity 3D模型展示框架篇之框架运用
    Unity 3D模型展示框架篇之自由观察(Cinemachine)
    Unity 3D模型展示框架篇之资源打包、加载、热更(Addressable Asset System | 简称AA)
    Unity 3D模型展示框架篇之资源打包、加载、热更(二)
    Unity 3D模型展示框架篇之ILRuntime快速入门



    前言

    本项目将整合之前Unity程序基础小框架专栏在Unity
    3D模型展示项目基础上进行整合,并记录了集成过程中对原脚本的调整过程。增加了Asset Bundle+ILRuntime热更新技术流程。


    本文章主要介绍如何与ILRuntime项目整合的过程与使用实例。

    一、整合过程

    1.热更工程增加测试类文件

    HotFix.cs提供三个方法公Unity工程调用。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace HotFix_Project
    {
        public class HotFix
        {
            void Awake()
            {
                UnityEngine.Debug.Log("Awake");
            }
            public  static void HelloWorld(string name,int age) {
                UnityEngine.Debug.Log("HelloWorld "+name+" "+ age);
            }
            public string Hello(string name) {
                return "hello " + name;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    2.Unity工程中增加新场景

    创建ILRuntime场景,创建ILRuntimeFramework脚本文件夹,增加脚本HotFixMgr.csHotFixMonoBehaviourAdapter.csDemoHelloWorld.cs脚本。
    在这里插入图片描述HotFixMgr.cs:AppDomain是ILRuntime的入口,最好是在一个单例类中保存,整个游戏全局就一个,这里为了示例方便,每个例子里面都单独做了一个。代码如下

    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using UnityEngine;
    
    public class HotFixMgr : MonoBehaviour
    {
       public  static HotFixMgr instance;
        public ILRuntime.Runtime.Enviorment.AppDomain appdomain;
        public static HotFixMgr Instance
        {
            get
            {
                if (instance==null)
                {
                    instance=new GameObject("HotFixMgr").AddComponent<HotFixMgr>();
                    instance.LoadHotFixAssembly();
                }
                return instance;
            }
        }
    
        // Start is called before the first frame update
        void Start()
        {
    
        }
        void LoadHotFixAssembly() {
    
            appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();
    #if UNITY_ANDROID
        WWW www = new WWW(Application.streamingAssetsPath + "/Hotfix.dll");
    #else
            WWW www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.dll");
    #endif
            while (!www.isDone)
                //yield return null;
                System.Threading.Thread.Sleep(100);
            if (!string.IsNullOrEmpty(www.error))
                Debug.LogError(www.error);
            byte[] dll = www.bytes;
            www.Dispose();
    #if UNITY_ANDROID
        www = new WWW(Application.streamingAssetsPath + "/Hotfix.pdb");
    #else
            www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.pdb");
    #endif
            while (!www.isDone)
                System.Threading.Thread.Sleep(100);
            if (!string.IsNullOrEmpty(www.error))
                Debug.LogError(www.error);
            byte[] pdb = www.bytes;
            System.IO.MemoryStream fs = new MemoryStream(dll);
            System.IO.MemoryStream p = new MemoryStream(pdb);
            appdomain.LoadAssembly(fs, p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider());
    
            OnILRuntimeInitialized();
        }
        void OnILRuntimeInitialized()
        {
            //appdomain.Invoke("Hotfix.Game", "Initialize", null, null);
    
    #if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)
            //由于Unity的Profiler接口只允许在主线程使用,为了避免出异常,需要告诉ILRuntime主线程的线程ID才能正确将函数运行耗时报告给Profiler
            appdomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
    #endif
    
            //下面再举一个这个Demo中没有用到,但是UGUI经常遇到的一个委托,例如UnityAction
            appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction>((action) =>
            {
                return new UnityEngine.Events.UnityAction(() =>
                {
                    ((System.Action)action)();
                });
            });
        }
        // Update is called once per frame
        void Update()
        {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    HotFixMonoBehaviourAdapter.cs:热更工程与Unity的MonoBehaviour适配进行调用。代码如下

    using ILRuntime.CLR.Method;
    using ILRuntime.CLR.TypeSystem;
    using ILRuntime.Runtime.Intepreter;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class HotFixMonoBehaviourAdapter : MonoBehaviour
    {
        // Start is called before the first frame update
    
        public string bindClass;
        private IType classType;
        private ILTypeInstance instance;
        IMethod update_method;
        private IMethod start_method;
        private IMethod OnDestroy_method;
    
        private void Awake()
        {
            classType = HotFixMgr.Instance.appdomain.LoadedTypes[bindClass];
            instance = (classType as ILType).Instantiate();
            IMethod awake_method = classType.GetMethod("Awake", 0);
            update_method = classType.GetMethod("Update", 0);
            start_method = classType.GetMethod("Start", 0);
            OnDestroy_method = classType.GetMethod("OnDestroy", 0);
    
            if (awake_method != null)
            {
                HotFixMgr.instance.appdomain.Invoke(awake_method, instance);
            }
        }
        void Start()
        {
            if (start_method != null)
            {
                HotFixMgr.instance.appdomain.Invoke(start_method, instance);
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            if (update_method != null)
            {
                HotFixMgr.instance.appdomain.Invoke(update_method, instance);
            }
        }
        private void OnDestroy()
        {
            if (OnDestroy_method != null)
            {
                HotFixMgr.instance.appdomain.Invoke(OnDestroy_method, instance);
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    DemoHelloWorld.cs:测试调用热更工程中的方法。代码如下

    using ILRuntime.CLR.Method;
    using ILRuntime.CLR.TypeSystem;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class DemoHelloWorld : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            string className = "HotFix_Project.HotFix";
            string funName = "HelloWorld";
             获取类型
            IType type = HotFixMgr.Instance.appdomain.LoadedTypes[className];
            //静态调用
            HotFixMgr.Instance.appdomain.Invoke(className, funName, null, "yxl", 30);
    
            // 创建实例
            object instance = (type as ILType).Instantiate();
            object res = HotFixMgr.Instance.appdomain.Invoke(className, "Hello", instance, "yxl");
            Debug.Log("实例化返回值" + res.ToString());
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    3.进行测试

    修改完热更工程一定要重新生成解决方案
    修改完热更工程一定要重新生成解决方案
    修改完热更工程一定要重新生成解决方案

    Unity项目中挂在脚本,并设置BindClass变量值,运行结果如下:
    在这里插入图片描述


    总结

    以上就是今天要讲的内容,本文仅仅简单整合了ILRuntime在Unity工程中如何调用热更工程的方法,介绍了如何在单例类中创建ILRuntime的入口AppDomain。在Unity工程里为了完整实现MonoBehaviour的所有特性,我们创建了Adapter适配器类,实现了AwakeStartOnDestroyUpdate。最后演示了如何调用热更工程中的静态方法、实例化方法、带有参数的方法。而ILRuntime提供了大量热更的案例能使我们快速便捷地掌握大家可以自行阅读了解,下篇介绍在项目怎么将热更工程的DLL(AA不能直接打包DLL哟)进行更新,以及如何进行AA+ILRuntime整合与应用。
    在这里插入图片描述

  • 相关阅读:
    Cpp/Qtday010906cpp基础
    Unicorn 嵌入Android系统
    LLM微调(一)| 单GPU使用QLoRA微调Llama 2.0实战
    kafka基础(1):官网解读-INTRODUCTION
    IllegalArgumentException
    JAVA也能用上Seq啦
    自接触svn之后对git的了解及其应用
    零知识证明:身份隐私中的ZK
    网络地址转换技术NAT(第九课)
    JSON和全局异常处理
  • 原文地址:https://blog.csdn.net/yxl219/article/details/126260935