Unity ILRuntime的基本实现流程(0基础)

 Windows-->package Manager,找到ILRuntime

如果找不到,配置一下根目录的manifest.json,文件头部增加

================

{
  "scopedRegistries": [
    {
      "name": "ILRuntime",
      "url": "https://registry.npmjs.org",
      "scopes": [
        "com.ourpalm"
      ]
    }
  ],
  "dependencies": {
    "com.ourpalm.ilruntime": "2.1.0-preview.1",
    "com.unity.2d.animation": "5.0.7",
    "com.unity.2d.pixel-perfect": "4.0.1",

===================

引入之后在Asset目录下会多一个Sample,打开目录下有sln结尾的工程文件,vs或者Rider打开

新建cs文件,测试

namespace HotFix_Project.HotFixTest
{
    //Helloworld
    public class HotFixHelloWorld
    {
        private static void HelloWorld()
        {
            UnityEngine.Debug.Log("HotPro:HelloWorld!!");
        }

        private static string HotStaticMethodWithString(string para)
        {
            UnityEngine.Debug.Log("HotPro:HotStaticMethodWithString!!"+para);
            return "HotPro:return HotStaticMethodWithString!!";
        }

        private string HotCallMethodWithString()
        {
            UnityEngine.Debug.Log("HotPro:HotCallMethodWithString!!");
            return "HotPro:return HotCallMethodWithString!!";
        }
    }
}
编译没问题,在Assets目录创建StreamingAssets文件,构建生成热更新项目,会生成dll文件到该目录

项目里创建初始化单例

using System;
using System.IO;
using UnityEngine;
using AppDomain = ILRuntime.Runtime.Enviorment.AppDomain;

namespace Merge_County.Scripts.ILRuntimeFramework
{
    public class HotFixMgr : MonoBehaviour
    { 
        //AppDomain是ILRuntime的入口,最好是在一个单例类中保存,整个游戏全局就一个,这里为了示例方便,每个例子里面都单独做了一个
        //大家在正式项目中请全局只创建一个AppDomain
        private static HotFixMgr _mInstance;

        // ReSharper disable Unity.PerformanceAnalysis
        public static HotFixMgr GetInstance()
        {
            if (_mInstance == null)
            {
                _mInstance = new GameObject("HotFixMgr").AddComponent<HotFixMgr>();
                _mInstance.LoadILRuntime();
                _mInstance.InitILRuntime();
            }
            return _mInstance;
        }
        public AppDomain Appdomain;
        private MemoryStream _fs;
        private MemoryStream _p;
        
        private readonly Boolean _isServer = false;
    
        private void InitILRuntime()
        {
#if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)
            //unity的Profiler接口只允许在主线程使用
            Appdomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
#endif
            //注册CLR绑定,避免过多的反射访问,提升性能
            ILRuntime.Runtime.Generated.CLRBindings.Initialize(Appdomain);
        
            Appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction>((act)=>
            {
                return new UnityEngine.Events.UnityAction(() =>
                {
                    ((Action)act).Invoke();
                });

            });
            Appdomain.DelegateManager.RegisterFunctionDelegate<Int32>();
            Appdomain.DelegateManager.RegisterDelegateConvertor<DG.Tweening.Core.DOSetter<Int32>>((act) =>
            {
                return new DG.Tweening.Core.DOSetter<Int32>((pNewValue) =>
                {
                    ((Action<int>)act)(pNewValue);
                });
            });
            Appdomain.DelegateManager.RegisterDelegateConvertor<DG.Tweening.Core.DOGetter<Int32>>((act) =>
            {
                return new DG.Tweening.Core.DOGetter<Int32>(() => ((Func<int>)act)());
            });
            Appdomain.DelegateManager.RegisterFunctionDelegate<Single>();
            Appdomain.DelegateManager.RegisterDelegateConvertor<DG.Tweening.Core.DOSetter<Single>>((act) =>
            {
                return new DG.Tweening.Core.DOSetter<Single>((pNewValue) =>
                {
                    ((Action<Single>)act)(pNewValue);
                });
            });
            Appdomain.DelegateManager.RegisterDelegateConvertor<DG.Tweening.Core.DOGetter<Single>>((act) =>
            {
                return new DG.Tweening.Core.DOGetter<Single>(() =>
                {
                    return ((Func<Single>)act)();
                });
            });
        }

        private void LoadILRuntime()
        {
            Appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();
//#if UNITY_ANDROID
            //WWW www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.dll");
//#else

            WWW www = new WWW("");

            if (_isServer)
            {
                www = new WWW("http://192.168.88.100/ILRuntime/" +"HotFix_Project.dll");
            }
            else
            {
                www = new WWW("file://" + Application.streamingAssetsPath + "/HotFix_Project.dll");
            }
            
//#endif
            while (!www.isDone) 
                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_Project.pdb");
//#else

            if (_isServer)
            {
                www = new WWW("http://192.168.88.100/ILRuntime/" + "HotFix_Project.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;
            _fs = new MemoryStream(dll);
            _p = new MemoryStream(pdb);
            try
            {
                //IL中间汇编,加载到引擎中
                Appdomain.LoadAssembly(_fs, _p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider());
            }
            catch 
            {
                Debug.Log("加载热更新DLL失败,请确保已经生成DLL文件");
            }
            OnILRuntimeInitialized();
        }

        void OnILRuntimeInitialized()
        { 
            Appdomain.Invoke("Hotfix.Game", "Initialize", null, null);
        } 
    }
}

 之后初始化之后可以调用测试的函数代码

using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using Merge_County.Scripts.Tools;

namespace Merge_County.Scripts.ILRuntimeFramework
{
    public class HotFixCall
    {
        private static HotFixCall _mInstance;
        public static HotFixCall GetInstance()
        {
            if (_mInstance == null)
            {
                _mInstance = new HotFixCall();
            }
            return _mInstance;
        }
        
        /// <summary>
        ///  调用没有返回值的静态方法 "HotFix_Project.HotFixHelloWorld" "HelloWorld"
        /// </summary>
        public void CallStaticMethod(string className,string methodName)
        {
            HotFixMgr.GetInstance().Appdomain.Invoke(className, methodName, null);
        }

        /// <summary>
        /// 调用string返回值的静态方法
        /// </summary>
        /// <returns></returns>
        public string CallStaticMethodWithString(string className,string methodName,string para)
        {
            // 获取类型
            IType type = HotFixMgr.GetInstance().Appdomain.LoadedTypes[className];
            // 获取方法
            IMethod method = type.GetMethod(methodName, 1);
            // 调用方法
            object returnValue =  HotFixMgr.GetInstance().Appdomain.Invoke(method, null, para);
            
            Debugger.Log(returnValue);
            // 输出返回值
            return "0";
        }

        /// <summary>
        /// 调用非静态方法
        /// </summary>
        /// <returns></returns>
        public string CallMethodWithString(string className,string methodName)
        {
            // 获取类型
            IType type = HotFixMgr.GetInstance().Appdomain.LoadedTypes[className];
            // 创建实例
            object instance = (type as ILType).Instantiate();
            // 获取方法
            IMethod method = type.GetMethod(methodName, 0);
            // 调用方法
            object returnValue = HotFixMgr.GetInstance().Appdomain.Invoke(method, instance);
            Debugger.Log(returnValue);
            // 输出返回值
            return "0";
        }
    }
}

另外可以选择实现MonoBehavior的Adapter

以下是热更工程代码:

using UnityEngine;

namespace HotFix_Project.HotFixTest
{
    //委托 MonoBehaviour 的方法
    public class HotFixMonoBehaviour
    {
        void Awake()
        {
            Debug.Log("HotPro:Awake");
        }

        private void btnClick()
        {
            Debug.Log("HotPro:btnClick");
        }
        
        void Start()
        {
            Debug.Log("HotPro:Start");
        }
        
        void Update() 
        {
            /*Debug.Log("HotPro:Update");*/
        }

        void OnDestroy()
        {
            Debug.Log("HotPro:OnDestroy");
        }
    }
}


之后在Unity工程内实现代码:

using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.Runtime.Intepreter;
using UnityEngine;

namespace Merge_County.Scripts.ILRuntimeFramework
{
    public class HotFixMonoBehaviourAdapter : MonoBehaviour
    {
        //挂载在游戏组件上,游戏组件会自动调用热更的mono方法
        public string bindClass;

        private IType classType;

        private ILTypeInstance instance;

        private IMethod update_method;

        private IMethod start_method;

        private IMethod ondestroy_method;
    
        public virtual void Awake()
        {
            //创建需要创建的类型
            classType = HotFixMgr.GetInstance().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("OnDestory", 0);

            if (awake_method != null)
            {
                HotFixMgr.GetInstance().Appdomain.Invoke(awake_method, instance);
            }
        }

        private void Start()
        {
            if (start_method != null)
            {
                HotFixMgr.GetInstance().Appdomain.Invoke(start_method, instance);
            }
        }

        // Update is called once per frame
        void Update()
        {
            if (update_method != null)
            {
                HotFixMgr.GetInstance().Appdomain.Invoke(update_method, instance);
            }
       
        }
        void OnDestroy()
        {
            if (ondestroy_method != null)
            {
                HotFixMgr.GetInstance().Appdomain.Invoke(ondestroy_method, instance);
            }
        }
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值