当前位置: 首页 > news >正文

网站开发用原生10种营销方法

网站开发用原生,10种营销方法,北京亦庄网站建设公司,新闻网站图解怎么做以下内容是根据Unity 2020.1.0f1版本进行编写的   目前游戏开发厂商主流还是使用lua框架来进行热更,如xlua,tolua等,也有的小游戏是直接整包更新,这种小游戏的包体很小,代码是用C#写的;还有的游戏就是通过…

以下内容是根据Unity 2020.1.0f1版本进行编写的

目前游戏开发厂商主流还是使用lua框架来进行热更,如xlua,tolua等,也有的小游戏是直接整包更新,这种小游戏的包体很小,代码是用C#写的;还有的游戏就是通过热更C#代码来实现热更新的。本篇就来学习一下。

1、热更C#代码的方法

AI时代,遇事不决,先问AI,下面就是百度问AI的答案:
在这里插入图片描述
在这里插入图片描述
可以看到,AI给出的答案大部分都是将C#代码编译成dll,然后在需要时动态加载对应的dll来实现代码的热更新的。下面就来尝试一下。

2、使用ILRuntime框架

ILRuntime官方文档:https://ourpalm.github.io/ILRuntime/public/v1/guide/tutorial.html
在这里插入图片描述
“scopedRegistries”: [
{
“name”: “ILRuntime”,
“url”: “https://registry.npmjs.org”,
“scopes”: [
“com.ourpalm”
]
}
],
在这里插入图片描述
如上图一,新建一个unity项目,然后在工程目录Packages下的manifest文件中增加图一框住的代码,保存。然后关闭Unity项目再重新打开。点击菜单栏Window->Package Manager打开PackageManager窗口,切换Packages切换到My Registries,可以看到刚刚加上去的ILRuntime包(如图二)。

选中后点击右下角箭头所指的install按钮就可以导入包体了(这里因为我已经导入过了所以显示的按钮是Remove)。这个包体还有示例Demo,有需要也可以一并导入到工程中。
在这里插入图片描述
导入的Demo用的是unsafe代码,导入后可能会有很多报错,点击菜单栏Edit->Project Settings打开ProjectSettings窗口,设置player页签中的OtherSettings,使工程允许使用unsafe代码。
在这里插入图片描述
接着尝试运行Demo,直接运行会报错,需要生成dll。
先用VisualStudio打开一次项目工程的sln文件,再打开下载的Demo包内工程的sln文件(如上图)。
在这里插入图片描述
在这里插入图片描述
在打开的HotFix_Project中,点击菜单栏生成->生成解决方案按钮,等待VS左下角出现生成成功提示。
在这里插入图片描述
此时回到Unity随便运行一个Examples场景,都不会有报错了。

在这里插入图片描述
接下来简单尝试一下,先做一个简单的界面(如上图),功能是点击下方左右两个按钮,点击哪边的按钮,就在中间的文本显示点击了哪边的按钮。

using UnityEngine;
using System.Collections;
using System.IO;
using System;public class AppCommon : MonoBehaviour
{static AppCommon instance;System.IO.MemoryStream fs;System.IO.MemoryStream p;public bool isLoaded = false;public static AppCommon Instance{get { return instance; }}//AppDomain是ILRuntime的入口,最好是在一个单例类中保存,整个游戏全局就一个,这里为了示例方便,每个例子里面都单独做了一个//大家在正式项目中请全局只创建一个AppDomainpublic ILRuntime.Runtime.Enviorment.AppDomain appdomain;//在awake方法中先加载好appdomainvoid Awake(){instance = this;StartCoroutine(LoadHotFixAssembly());}IEnumerator LoadHotFixAssembly(){//首先实例化ILRuntime的AppDomain,AppDomain是一个应用程序域,每个AppDomain都是一个独立的沙盒appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();//正常项目中应该是自行从其他地方下载dll,或者打包在AssetBundle中读取,平时开发以及为了演示方便直接从StreammingAssets中读取,//正式发布的时候需要大家自行从其他地方读取dll//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//这个DLL文件是直接编译HotFix_Project.sln生成的,已经在项目中设置好输出目录为StreamingAssets,在VS里直接编译即可生成到对应目录,无需手动拷贝
#if UNITY_ANDROIDWWW www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.dll");
#elseWWW www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.dll");
#endifwhile (!www.isDone)yield return null;if (!string.IsNullOrEmpty(www.error))UnityEngine.Debug.LogError(www.error);byte[] dll = www.bytes;www.Dispose();//PDB文件是调试数据库,如需要在日志中显示报错的行号,则必须提供PDB文件,不过由于会额外耗用内存,正式发布时请将PDB去掉,下面LoadAssembly的时候pdb传null即可
#if UNITY_ANDROIDwww = new WWW(Application.streamingAssetsPath + "/HotFix_Project.pdb");
#elsewww = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.pdb");
#endifwhile (!www.isDone)yield return null;if (!string.IsNullOrEmpty(www.error))UnityEngine.Debug.LogError(www.error);byte[] pdb = www.bytes;fs = new MemoryStream(dll);p = new MemoryStream(pdb);try{appdomain.LoadAssembly(fs, p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider());}catch{Debug.LogError("加载热更DLL失败,请确保已经通过VS打开Assets/Samples/ILRuntime/1.6/Demo/HotFix_Project/HotFix_Project.sln编译过热更DLL");}InitializeILRuntime();OnHotFixLoaded();}private void OnDestroy(){fs.Close();p.Close();}unsafe void InitializeILRuntime(){
#if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)//由于Unity的Profiler接口只允许在主线程使用,为了避免出异常,需要告诉ILRuntime主线程的线程ID才能正确将函数运行耗时报告给Profilerappdomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
#endif//这里做一些ILRuntime的注册appdomain.RegisterCrossBindingAdaptor(new MonoBehaviourAdapter());appdomain.RegisterValueTypeBinder(typeof(Vector3), new Vector3Binder());appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction>((act) =>{return new UnityEngine.Events.UnityAction(() =>{((Action)act)();});});ILRuntime.Runtime.Generated.CLRBindings.Initialize(appdomain);}unsafe void OnHotFixLoaded(){isLoaded = true;Debug.Log("AppDomain Loaded");}
}

首先在Unity中新建一个名叫AppCommon的脚本,用于定义一些项目内通用的单例类。这里主要是定义一个叫appdomain的类,在Demo中是建议全局只创建一个的。
每个Demo都会有加载这个appdpmain的方法,将代码复制到AppCommon类中,在其InitializeILRuntime方法中注册好全部需要用到的事件等。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Intepreter;
using ILRuntime.Runtime.Stack;public class MyView1 : MonoBehaviour
{static MyView1 instance;public static MyView1 Instance{get { return instance; }}void Start(){instance = this;StartCoroutine(LoadHotFixAssembly());}IEnumerator LoadHotFixAssembly(){while(!AppCommon.Instance.isLoaded){yield return 0;}OnHotFixLoaded();}void OnHotFixLoaded(){SetupCLRRedirection();SetupCLRRedirection2();AppCommon.Instance.appdomain.Invoke("HotFix_Project.TestMyView1", "ShowView", null, gameObject);}unsafe void SetupCLRRedirection(){//这里面的通常应该写在InitializeILRuntime,这里为了演示写这里var arr = typeof(GameObject).GetMethods();foreach (var i in arr){if (i.Name == "AddComponent" && i.GetGenericArguments().Length == 1){AppCommon.Instance.appdomain.RegisterCLRMethodRedirection(i, AddComponent);}}}unsafe void SetupCLRRedirection2(){//这里面的通常应该写在InitializeILRuntime,这里为了演示写这里var arr = typeof(GameObject).GetMethods();foreach (var i in arr){if (i.Name == "GetComponent" && i.GetGenericArguments().Length == 1){AppCommon.Instance.appdomain.RegisterCLRMethodRedirection(i, GetComponent);}}}unsafe static StackObject* AddComponent(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj){//CLR重定向的说明请看相关文档和教程,这里不多做解释ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;var ptr = __esp - 1;//成员方法的第一个参数为thisGameObject instance = StackObject.ToObject(ptr, __domain, __mStack) as GameObject;if (instance == null)throw new System.NullReferenceException();__intp.Free(ptr);var genericArgument = __method.GenericArguments;//AddComponent应该有且只有1个泛型参数if (genericArgument != null && genericArgument.Length == 1){var type = genericArgument[0];object res;if (type is CLRType){//Unity主工程的类不需要任何特殊处理,直接调用Unity接口res = instance.AddComponent(type.TypeForCLR);}else{//热更DLL内的类型比较麻烦。首先我们得自己手动创建实例var ilInstance = new ILTypeInstance(type as ILType, false);//手动创建实例是因为默认方式会new MonoBehaviour,这在Unity里不允许//接下来创建Adapter实例var clrInstance = instance.AddComponent<MonoBehaviourAdapter.Adaptor>();//unity创建的实例并没有热更DLL里面的实例,所以需要手动赋值clrInstance.ILInstance = ilInstance;clrInstance.AppDomain = __domain;//这个实例默认创建的CLRInstance不是通过AddComponent出来的有效实例,所以得手动替换ilInstance.CLRInstance = clrInstance;res = clrInstance.ILInstance;//交给ILRuntime的实例应该为ILInstanceclrInstance.Awake();//因为Unity调用这个方法时还没准备好所以这里补调一次}return ILIntepreter.PushObject(ptr, __mStack, res);}return __esp;}unsafe static StackObject* GetComponent(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj){//CLR重定向的说明请看相关文档和教程,这里不多做解释ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;var ptr = __esp - 1;//成员方法的第一个参数为thisGameObject instance = StackObject.ToObject(ptr, __domain, __mStack) as GameObject;if (instance == null)throw new System.NullReferenceException();__intp.Free(ptr);var genericArgument = __method.GenericArguments;//AddComponent应该有且只有1个泛型参数if (genericArgument != null && genericArgument.Length == 1){var type = genericArgument[0];object res = null;if (type is CLRType){//Unity主工程的类不需要任何特殊处理,直接调用Unity接口res = instance.GetComponent(type.TypeForCLR);}else{//因为所有DLL里面的MonoBehaviour实际都是这个Component,所以我们只能全取出来遍历查找var clrInstances = instance.GetComponents<MonoBehaviourAdapter.Adaptor>();for (int i = 0; i < clrInstances.Length; i++){var clrInstance = clrInstances[i];if (clrInstance.ILInstance != null)//ILInstance为null, 表示是无效的MonoBehaviour,要略过{if (clrInstance.ILInstance.Type == type){res = clrInstance.ILInstance;//交给ILRuntime的实例应该为ILInstancebreak;}}}}return ILIntepreter.PushObject(ptr, __mStack, res);}return __esp;}
}

然后还是在Unity中新建一个名叫MyView1的脚本,这个脚本的功能其实只是等待上述的appdomain类加载完之后,然后调用加载的dll内部的类以及方法即可。实际逻辑是写到HotFix_Project里的,也只有HotFix_Project里的代码能热更。
这里写的比较简单,大部分代码是抄MonoBehaviourDemo的,实际上就是需要使appdomain注册自定义实现AddComponent方法和GetComponent方法。这样,在热更的代码中就可以通过AddComponent方法来把C#代码以组件的形式挂载到对应的GameObject中。
在这里插入图片描述
在这里插入图片描述
最后就是热更代码部分。
因为要用到Unity UI部分的方法,所以需要将UnityEngine.UI的dll复制过来并加入到HotFix_Project的引用中。(先把dll复制到UnityDlls目录下,然后再在VS上右键添加引用,在打开的窗口中点击右下角浏览,然后选择复制的dll文件即可)

using UnityEngine;
using UnityEngine.UI;namespace HotFix_Project
{class TestMyView1 : MonoBehaviour{private Button btn1;private Button btn2;private Text text;void Start(){btn1 = gameObject.transform.Find("btn1").GetComponent<Button>();btn2 = gameObject.transform.Find("btn2").GetComponent<Button>();btn1.onClick.AddListener(OnClickBtn1);btn2.onClick.AddListener(OnClickBtn2);text = gameObject.transform.Find("Text").GetComponent<Text>();}void OnClickBtn1(){text.text = "点击了左边的按钮";}void OnClickBtn2(){text.text = "点击了右边的按钮";}public static void ShowView(GameObject go){go.AddComponent<TestMyView1>();}}
}

接着在HotFix_Project新建一个名叫TestMyView1的C#脚本,实现上面描述的功能就可以了。这一部分代码就是可热更的。
写好代码后,点击HotFix_Project菜单栏的生成->重新生成解决方案按钮,即可运行Unity。
效果如下:
在这里插入图片描述
最后,如果需要实现热更,就是在AppCommon加载appdomain的协程中,修改一下加载的文件位置(如上图框住的部分,这里我没试)。
所以实际上,C#代码热更就是将代码编译成dll,然后在加载后以反射调用或者委托等方式来调用写在dll内部的类和方法。因此每次热更只需要重新编译生成dll就可以了。
在这里插入图片描述
在这里插入图片描述
此外,该框架还能生成一些CLR绑定的代码,用于减少反射调用的消耗。(实际上这里的做法有点类似于tolua框架)

代码仓库地址:https://gitee.com/chj–project/CSharpHotUpdate


文章转载自:
http://dinncolordy.tpps.cn
http://dinncotownwear.tpps.cn
http://dinncotithonia.tpps.cn
http://dinncomiscellanea.tpps.cn
http://dinncoleatherboard.tpps.cn
http://dinncoyawey.tpps.cn
http://dinncomatlock.tpps.cn
http://dinncocadetcy.tpps.cn
http://dinncoautolysis.tpps.cn
http://dinncobeneficial.tpps.cn
http://dinncomester.tpps.cn
http://dinncobim.tpps.cn
http://dinncofimbriate.tpps.cn
http://dinnconock.tpps.cn
http://dinncopolybasic.tpps.cn
http://dinncoparcener.tpps.cn
http://dinncotentage.tpps.cn
http://dinncoaboriginally.tpps.cn
http://dinncomiskick.tpps.cn
http://dinncounmilitary.tpps.cn
http://dinncobookstand.tpps.cn
http://dinncocashew.tpps.cn
http://dinncosequestrum.tpps.cn
http://dinncojamming.tpps.cn
http://dinncoimpracticality.tpps.cn
http://dinncorepressive.tpps.cn
http://dinncodisbursable.tpps.cn
http://dinncotrotskyist.tpps.cn
http://dinncotrimmer.tpps.cn
http://dinncovalorisation.tpps.cn
http://dinncosailcloth.tpps.cn
http://dinncotrigeminal.tpps.cn
http://dinncoquotha.tpps.cn
http://dinncologgats.tpps.cn
http://dinncoconscience.tpps.cn
http://dinncoposturepedic.tpps.cn
http://dinncowilled.tpps.cn
http://dinncobludgeon.tpps.cn
http://dinncoalod.tpps.cn
http://dinncoibiza.tpps.cn
http://dinncometeorologist.tpps.cn
http://dinncokbl.tpps.cn
http://dinncoflint.tpps.cn
http://dinncoeunomic.tpps.cn
http://dinncocrematorium.tpps.cn
http://dinncoautoanalyzer.tpps.cn
http://dinncouncharitably.tpps.cn
http://dinncokara.tpps.cn
http://dinncoproteinaceous.tpps.cn
http://dinncofilopodium.tpps.cn
http://dinncolunisolar.tpps.cn
http://dinncoforth.tpps.cn
http://dinncotermagancy.tpps.cn
http://dinncoantiquate.tpps.cn
http://dinncoteam.tpps.cn
http://dinncofishpaste.tpps.cn
http://dinncodiscriminating.tpps.cn
http://dinncofeeler.tpps.cn
http://dinncocinematize.tpps.cn
http://dinncobibliophile.tpps.cn
http://dinncocatoptrical.tpps.cn
http://dinncodaunting.tpps.cn
http://dinncobandicoot.tpps.cn
http://dinncodoesnot.tpps.cn
http://dinncogaselier.tpps.cn
http://dinncodeodand.tpps.cn
http://dinncoquintuplicate.tpps.cn
http://dinncoriproarious.tpps.cn
http://dinncorazzia.tpps.cn
http://dinncodefi.tpps.cn
http://dinncomony.tpps.cn
http://dinncoallamanda.tpps.cn
http://dinncofactor.tpps.cn
http://dinncopacuit.tpps.cn
http://dinncoreread.tpps.cn
http://dinncoeutectoid.tpps.cn
http://dinncoonwards.tpps.cn
http://dinncocyclazocine.tpps.cn
http://dinncosoviet.tpps.cn
http://dinncodam.tpps.cn
http://dinncoestrum.tpps.cn
http://dinncoarchean.tpps.cn
http://dinncoresurrect.tpps.cn
http://dinncochagos.tpps.cn
http://dinncotrixie.tpps.cn
http://dinncowanna.tpps.cn
http://dinncomspe.tpps.cn
http://dinncomalayan.tpps.cn
http://dinnconematocystic.tpps.cn
http://dinncodefinitive.tpps.cn
http://dinncocoatrack.tpps.cn
http://dinncococonut.tpps.cn
http://dinncofloodtime.tpps.cn
http://dinncoprocurable.tpps.cn
http://dinncosurculose.tpps.cn
http://dinncoploughshare.tpps.cn
http://dinncowainscot.tpps.cn
http://dinncojubilize.tpps.cn
http://dinncostandoffishly.tpps.cn
http://dinncojove.tpps.cn
http://www.dinnco.com/news/97592.html

相关文章:

  • 网站开发人员需要具备的能力搜索引擎优化技术都有哪些
  • 房地产政策最新消息成都seo外包
  • wordpress 4.4.2漏洞石家庄百度搜索优化
  • 保定网络公司建设网站搜狗seo软件
  • 网站建设费入什么总账科目软文广告范例大全
  • 设计中国第一架飞机seo建站
  • 一级域名和二级域名做两个网站百度云搜索引擎入口盘多多
  • 石家庄seo公司超级seo外链
  • max age 0 wordpress东莞seo排名扣费
  • jsp做的零食小网站怎么做好网络营销
  • 企业在线管理系统珠海百度关键字优化
  • bootstrop新闻网站开发站长之家素材网站
  • 北京网站建设价格如何提高seo关键词排名
  • 手机网站前端用什么做网站关键词收录查询
  • 贵阳做网站seo怎么推广
  • 上海建筑建材业网站网站设计公司苏州
  • 网站代码怎么查看网页设计制作网站教程
  • 北京服装网站建设seo广告投放是什么意思
  • 做网站选哪家公司好百度怎么做推广
  • wordpress 手机模版优化教程网站推广排名
  • 湖南省交通建设质量安全监督管理局网站seo观察网
  • 响应式WordPress企业主题首页排名优化公司
  • 做的比较好的企业网站百度一下首页版
  • 免费b网站推广自己有货源怎么找客户
  • xsl做书店网站com网站域名注册
  • 企业每年向工商网站做申报页面设计漂亮的网站
  • 创建网站制作首页新疆头条今日头条新闻
  • wordpress 手机站seo数据
  • 湖南网站建设公司 要上磐石网络百度小说排行榜总榜
  • mac 网站开发 软件杭州营销策划公司排名