tolua小项目实战

0 去试试创业网

此时时间是正常的,只能归结于tolua框架对于立马获取Time.realtimeSinceStartup的问题。综合考虑之后,把获取服务器时间放在登录请求发送之后,还是直接使用Time.realtimeSinceStartup获取。

如果稍微延迟一点再获取,时间就正常了。很明显初次获取的时间是错误的。 怀疑应该是在lua里开始直接获取时间是不正常的,使用LuaUtil工具在试看看。

我本地测试可以发现,如果在登录界面启动时,就请求服务器时间,此时的Time.realtimeSinceStartup为0.(按道理肯定不应该为0,因为游戏已经启动很久了)

tolua小项目实战

当从服务器请求获取时间时,保存游戏启动时间Time.realtimeSinceStartup,然后通过计算每次获取时间时,游戏启动时间差来估算当前服务器的时间。此方式是有一定的误差,但还算可接受范围内。

这一年,我们在不同的城市与各位开发者们交流探索,一步步走来,既是成长也是沉淀。我们希望能有机会可以走到更多开发者的面前,更加深入地了解项目的性能问题西南农村创业种植果树,更好地助力游戏开发团队打造完整的工具链。

我们从大量研发团队的日常使用场景出发,分享日常研发中需要注意和掌握的性能和质量保障的关键环节,以及各大游戏团队在使用UWA Pipeline过程中的最佳实践,并对UWA Pipeline流水线进行了现场展示,和开发者们互动交流。

除了核心概念之外,我们还会讨论许多有用的技巧,它们都可以用在你的程序中,比如说在场景中移动,做出漂亮的光照,加载建模软件导出的自定义模型,做一些很酷的后期处理技巧等。最后,我们也将会使用我们已学的知识从头开始做一个小游戏,让你真正体验一把图形编程的魅力。

学习(和使用)现代OpenGL需要用户对图形编程以及OpenGL的幕后运作有非常好的理解才能在编程中有很好的发挥。所以,我们会首先讨论核心的图形学概念,OpenGL怎样将像素绘制到屏幕上,以及如何利用黑科技做出一些很酷的效果。

本文是LearnOpenGL教程的中文翻译,英文版的地址为:Learn OpenGL, extensive tutorial resource for learning Modern OpenGL

本文介绍了一些3D渲染技术的组合思路,并用来对中国传统绘画中的宋代水墨山水画风格进行模仿实现。文章思路同样可以用于油画、水彩、素描以及漫画等其他美术风格方向的渲染。

本课程主要记录了笔者项目初期碰到的并值得一说的实际业务问题,涵盖了比较多客户端框架设计的内容,以及有效提升开发者编程体验的内容。

第四章是不定期更新的支持章节,主要会更新一些难以归类,项目中又必须涉及的琐碎知识。目前更新了BlobAsset相关内容(提供ECS端使用配置的方法)。

第三章资源系统篇,再次以一个项目中必须准备的大型方案(GameObject与ECS混用方案)为实战用例,手把手带领大家从会用DOTS到掌握DOTS。

本课程将会从实际的MMORPG类型的战斗系统开发着手,重点讲解如何正确的使用ET框架进行大型MMORPG的战斗系统开发。在课程当中,我们将会触及MMORPG网络游戏战斗系统开发的方方面面。首先我们将会带着同学们手把手地实现一整套的MMORPG战斗技能管线系统,并且在此基础上,通过抽象和组合的方式,以最为通用的设计来实现各种MMORPG网络游戏中的战斗与技能系统。

本课程的主要学习内容是如何使用ET框架(在Github上有着极高人气的基于.Net的跨平台,开源,高性能,全栈式开发与多进程分布式部署的网络游戏开发框架)进行MMORPG网络游戏的战斗系统开发。

所以本门课程重点围绕ET框架8.0的全新特性,对其原理与设计思路展开讲解,并通过小案例的形式,帮助读者梳理ET框架的设计思路与开发思想,从而进一步学会和掌握ET框架的基本使用,并带领读者掌握和熟悉使用ET框架8.0版本进行游戏前后端全栈式开发的基本流程。

ET框架经过长期的实践和更新,升级至最新8.0版本,拥有了更加强大和灵活的架构,由于ET框架8.0版本进行了一系列重大的升级,架构得到了全新的迭代。大多数初学者与客户端开发人员会在初次接触ET框架时,会因为缺乏网络编程通识和其自身固有的面向对象开发习惯,从而被劝退或者编写出极其”不规范“的ET框架业务代码。并且由于ET框架8.0版本引入的多线程纤程的机制,进一步加深了ET框架的理解和使用的门槛。

UnityEditor.Build.Content.ContentBuildInterface下面的方法获取到的依赖信息是准确的。如下面两个函数:

比较明显的是,当Prefab嵌套时,Manifest数据会显示Prefab依赖被嵌套的Prefab;而SpriteAtlas和Sprite依赖关系是反的。其他还有很多情况会额外依赖不需要的资源。用WebExtract解开AssetBundle本身,里面的数据是正确的依赖数据。

框架搭好后,满足一些限制条件(非硬性限制,主要是避免麻烦,限制主要是1个,可热更部分的代码不要继承不可热更的代码,不继承MonoBehaviour是这个限制的子集),写逻辑的同学开发方式和原生C#开发完全一样,包括调试。

19年9月Google Play强制要求APP都支持64位,Unity的应对方案是Android IL2CPP,暂时没有支持Mono Backend 64位的打算,而且Unity IL2CPP实现的真不怎么样。所以到时候只能是IL2CPP + ILRuntime的方式,性能差的一大截,主要慢在ILRuntime上。

热更新部分的代码都不继承MonoBehaviour,也就是都不挂脚本,非热更新部分随意,热更新对MonoBehaviour这种比较特殊的东西的支持都挺麻烦,要么不用;要么只是做个不可热更新的消息转发层;要么开发时挂脚本,打包时用某种特殊的方式把它变成代码里动态AddComponent。

然后我们首先用xLua打补丁修Bug,这样成本最低,后来运营要求能通过热更新加功能,而不仅仅是改Bug,那么要么用Lua写所有可能会被热更新的代码,这需要把现有的大量C#代码翻译过来;要么想办法让C#能热更新。很自然就选择了后者+ILRuntime的方法。

说回正题,一般热更新分两块:代码+资源。资源热更新几乎都是通过AssetBundle来实现,代码热更新可以用某种解释器+解释执行的语言来实现,可供选择的有Lua、AS3、Python、JS、C#等,据我所知,主流是Lua,次主流是C#.

A2:ILRuntime本质上就是为了iOS热更(代码)而开发的,Android热更可以用ILRuntime,也可以完全不用。

A1:Lua缺点是很多,原因很大一部分是因为大家用的是ToLua这种一揽子解决方案。本身Lua就慢,ToLua为了让大家像C++上使用Lua那样快速上手,在底层做了不少事情,包括对UserData的处理(导致了Lua的GC和C#的GC冲突)和对LuaState的OOP化。对C#的无脑Wrap和对Lua的OOP改造也进一步加剧了这些问题。更何况,Lua和C#之间并没有大家想象中那么契合。一个最简单的例子,任何Lua传给C#的String都是新的GC Alloc。然而,对于热更新方案,我们并没有太多的选项,Lua算是一种比较成熟、性能上勉强能用的方案,最重要的是,用的人要真的会(不仅仅是会语法),那么性能上才不会有大问题。当然,还是要期待大牛研发出更优雅和优秀的方案。

除了C#反射这个老办法、或者Lua,大家还用了什么办法吗?以及有人不用热更新吗?想在立项阶段先做个调研,避免之后填坑,谢谢各位!

Addressables.UpdateCatalogs()后告诉你其中5个更新了。那么如果你立即调用GetDownloadSizeAsync和DownloadDependenciesAsync,可以马上传入这5个Key。另外一种情况可能你这一次游戏中UpdateCatalogs获得5个更新。但是要到下一次启动游戏才调用GetDownloadSizeAsync和DownloadDependenciesAsync,那你可以把这20个Keys都传进去。

第二,AA其实只比较资源的Hash,因此没有版本号概念,所以不存在中间版本,永远是最新版本和母包。这个PlayerVersionOverride指你打Player的那个版本号,一般是更新母包时才递增。这种做法可以保证不管玩家手里是哪份资源,都能更到最新的,并且避免中间的逐版本升级流程。

A3:第一,你用Disable Catalog Update on StartUp方式启动,就是默认不更新Catalog,但是在走后面更新的时候,Catalog其实已经更新完了,再调用API更新Catalog自然没有了。这时只要去GetDownloadSize然后直接更资源就行了。

Addressables.LoadContentCatalogAsync()加载,然后得到IResourceLocator的所有Key,把所有Key传入下载列表中进行下载资源文件。

Addressables.UpdateCatalogs(),自己去服务器上下载Catalog文件,如果下载到一半了,取消,不修改版本号。下次进来接着去服务器下载Catalog文件。然后自己下载的Catalog文件可以用

这种情况下是否可以使用Addressables.ClearResourceLocators()和 Caching.ClearCache()清理缓存和已经下载好的资源,再次触发热更,这时catalogs.Count 应该是不等于0的吧?

利用Addressable进行热更,采用Disable Catalog Update on StartUp方式,当更新进度没有完成时杀掉游戏,再重新启动游戏,此时catalogs.Count已经等于0,并不会在此触发更新,但其实还有部分资源未更新到,这种情况下应该怎么处理?

上面所谓的减少IO,不是减少IO本身的读取量,只是少了一个IO句柄,直接把两个原始资源打到一个Bundle内,其实是一样的。那么问题就变成了怎么合理打包Bundle。

A:AssetBundle已经是一个VFS了,再在上面多管理一层,从各方面来说不合理,还有可能出现IO句柄持有冲突的问题。

看有文章说可以利用接口LoadFromFile(string path, uint crc, ulong offset);来实现资源包合并为一个打包,且能减少IO操作,不知流程是否是如下理解:

在Lua虚拟机内部监测死循环的情况,然后自主中断,抛出Error。这个是我们现在在用的方式,改造Lua虚拟机,监测一定时间内一直在执行某些字节码超过一定阈值就认为自己是在死循环把自己结束掉。当然还有一些别的条件,比如栈深度检测等等。这种自主中断并且抛错的方式其实更加完美。具体实现可以参考这个文章的思路:

建立一个完整的沙盒环境,类似Dock,这个环境内运行逻辑,外部可以把这个环境销毁掉,不会对外部造成任何影响,这个在Unity下可能难度比较大,要做逻辑和表现的分离,然后构建一个纯逻辑层的运行环境。

很可能是这个Dispose操作是由Lua驱动执行,相当于在Lua执行的过程中把Lua虚拟机给释放了,改为只由C#执行即可。

xLua/Assets/XLua/Doc/faq.md at master · Tencent/xLua · GitHub

bool isCompletedSuccessfully = task.Wait(TimeSpan.FromMilliseconds(1500)); //1.5s timeout

isSucceed = sandbox.DoString(xxxx)//这里简化一下.核心就是加载这个脚本执行DoString

我使用xLua作为游戏的内嵌脚本语言云南磨憨做什么小生意好,允许玩家自定义脚本。现在有个玩家在脚本里面写了一个死循环,当我用DoString去加载这个脚本时候会直接卡死,于是我在外面加入了一个Task:

UWA DAY技术沙龙:开发者技术沙龙。我们带着最新的技术、工具和经验去到了广州、成都、杭州、北京、上海、深圳、厦门七座城市,希望与更多的开发者面对面的交流,让更多开发者受益。

UWA学堂:传播游戏行业的体系化的进阶学习内容。UWA学堂作为面向开发者的在线学习平台,目前已经上线272门课程,涵盖了3D引擎渲染、UI、逻辑代码等多个模块,拥有完整的学习体系,一直致力于为广大的开发者提供更丰富、更优质的学习资源。

UWA问答:帮助游戏行业开发者找到更好的答案。UWA从2016年开始整理发布问答,以技术交流栏目【厚积薄发】系列每周进行推送,精选了开发团队中实际遇到的问题以及解决方案,至今已经发布了367期,累计发布约1800条精选QA,相信帮助了不少开发者们答疑解惑。

弹指间,2023年已接近尾声,这一年UWA社区为游戏行业开发者和期望步入游戏圈的学子们提供了多类型的社区服务,包括技术博客、问答、开源库、学堂、训练营、技术沙龙等。让我们一同回顾这一年来UWA的脚步,希望未来的每一步也都能有大家的陪伴。

精通C#、C++、Shader、Socket、iOS、HTML5、JS、ReactNative编程等。授课经验丰富。对Unity引擎有深刻的理解,虚幻4,寒霜3引擎也有一定的研究,喜欢钻研各种新型的技术知识。

专题: 农村创业篇   农村民创业   农村创业.