1)对于AI逻辑写在Lua中的问题
2)Shader中宏的作用
3)Update中的new Struct对象
4)通过在编辑的预制体中获取资源门路
这是第266篇UWA技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫10分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)
Lua
Q:当初战斗的外围逻辑都在xLua外面,蕴含了AI的逻辑,这部分计算量极大,会造成画面卡死。
尝试过用Thread把xLua虚拟机包一层,后果还是会报Main Thread的谬误。也尝试用闭包的形式,从Lua回传到CSharp,用System.Action接住,而后丢线程外面跑,然而会卡断主线程。
当初想尝试用两个Lua虚拟机,一个放Thread外面只跑战斗,其余的放在主Lua虚拟机中。那么整个游戏运行起来,会有3个虚拟机:Mono、xLua和xLuaInThread。
策动心愿AI做得聪慧一些,对应的思考维度和运算量都会大幅提高。不晓得是否有其余举荐的计划?
A1:我感觉不是虚拟机方向的问题:
- Lua和Unity交互的细节没有把控好,比方重复在lua.transform.position等等相似的。
- 不论是Tolua还是xLua,并不是说齐全就不必C#了。应该是基于几个准则:扩展性、热更性和性能,比方MMORPG的头顶UI必定不是全副是Lua开发的,业务在Lua然而挪动那些必定是C#(一旦做完了,接下来简直不会再动到C#代码了)。
- Lua和C#交叉的细节须要把控。
- Lua自身的应用细节也须要把控好。
感激沈杰@UWA问答社区提供了答复
A2:不须要多个虚拟机。能够浏览《游戏编程精粹》里的这两篇文章(年代有点久了不记得是哪一本,也不记得具体讲了那些内容,只是取得了思路后,本人实现过):
- 用于游戏对象AI的微线程
- 应用微线程治理AI
我在已经的我的项目中实现基于协程的工作管理器,大抵有这些特点:
- 每个游戏对象运行的脚本在独立创立的协程上。
每个协程入口对立采纳相似C语言的入口办法标准,如:
- 入口函数Main。
- 随眠函数Sleep,Yield,Waitframe,Waittime(这些办法能够准确管制AI的计算频率与精度)。
- 退出相干办法Exit,Atexit。
- 对立在宿主程序中,对游戏中多个协程进行按需调度,比方期待指定工夫,帧数后调用Resume唤醒协程。
感激lujian@UWA问答社区提供了答复
Shader
Q:Particle Additive Shader中应用了该宏:UNITY\_DECLARE\_DEPTH\_TEXTURE(\_CameraDepthTexture);,查了一下没找到相干阐明。字面了解是申明了一个深度图。
在默认管线(向前渲染)中,依照惯例了解深度图须要通过设置Camera的depthTextureMode来指定。还请各位指教。
A:Shader中很多宏确实是没有官网阐明的,咱们须要去CGInclude文件夹中寻找其确切定义。
UNITY_DECLARE_DEPTH_TEXTURE在HLSLSupport.cginc里:
确实是为了申明一张图,回到Particle Add.shader中发现是为了申明深度图:
这是为了在片元着色器中的深度采样做筹备:
该SAMPLE_DEPTH_TEXTURE_PROJ办法同样在HLSLSupport.cginc中:
而后持续在该文件中找tex2Dproj:
由此可见这些操作就是在相机保留的深度图中,通过tex2D获取了深度,为LinearEyeDepth筹备参数从而失去场景深度。该Shader通常在开了软粒子之后被用到。
感激翟孟飞@UWA问答社区提供了答复
Script
Q:Struct中蕴含String字段,如果在Update中new,会不会有GC问题?思考是否须要用缓存池来解决,目前我测试了一下将Struct改成Class是必定有,如果是Struct类型,就没找到。
A1:对Class进行new是会调配堆内存,然而这个堆内存不肯定是String字段造成的。Class的实例自身就会占用堆内存,而它的字段会不会造成堆内存调配,取决于new的时候会不会对类型进行实例化。实例化的时候给String赋值,如果是间接确定的字符串内容,编译器会主动进行缓存优化,只会在第一帧创立字符串分配内存。
至于Struct,构造体作为值类型自身不会占用堆内存。对Struct进行new会不会调配堆内存,取决于new的时候,它的字段会不会实例化,会不会占用堆内存。如果Struct没有写构造函数,即便外面有援用类型,在new Struct的时候也不会实例化,不会调配堆内存。如果写了构造函数,就要看构造函数外面是否调配堆内存了。String的状况与上文提到的统一。
感激Prin@UWA问答社区提供了答复
A2:C#语法中除了构造函数造成的堆内存调配,还有构造体对外传递造成栈上逃逸问题。具体表现是结构的构造体作用域不仅局限在Update函数内。
在Unity的Playable模块里能够见到大量的ref Struct签名,是C# 7里专门解决栈逃逸的语法,依葫芦画瓢即可。
感激陈xx@UWA问答社区提供了答复
Script
Q:我想调用AssetDatabase.GetAssetPath 获取资源门路,但我点击图1物体,应用AssetDatabase.GetAssetPath(gameObject),却获取不到。想请问:如何通过图1获取到图2对应的物体门路?
A1:PrefabUtility.GetNearestPrefabInstanceRoot用来获取最近的预制体实例;Root PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot用来获取预制体门路。
[MenuItem("Tools/GetPrefabInstancePath")] public static void GetPrefabInstancePath() { if (null != Selection.activeGameObject) { if (PrefabUtility.IsPartOfPrefabInstance(Selection.activeGameObject)) { var path = PrefabUtility.GetPrefabAssetPathOfNearestInstanceRoot(Selection.activeGameObject); Debug.Log("Prefab Path:" + path); } } }
感激马三小伙儿@UWA问答社区提供了答复
A2:同意楼上的答复,此处我再稍作补充:
PrefabUtility.GetNearestPrefabInstanceRoot和AssetDatabase.GetAssetPath,前者针对的是曾经实例进去的对象(官网:返回指定对象所属的最近预制件实例根的资源门路),后者针对的是资源(官网:返回绝对于我的项目文件夹的资源门路名称)。题主的问题属于是前者,如果间接点击资源并用AssetDatabase.GetAssetPath,就能够获取到资源门路。
感激翟孟飞@UWA问答社区提供了答复
20210906
更多精彩问题等你答复~
1.Vulkan API的性能及兼容性
2.Unity TMP字体计划如何抉择
3.如何实现AAB包的增量更新
封面图来源于:Daydream Renderer for Unity
Daydream Renderer是一组脚本和着色器,旨在容许在Daydream平台上以60fps的帧率实现高质量实时渲染。
明天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题兴许都只是冰山一角,咱们早已在UWA问答网站上筹备了更多的技术话题等你一起来摸索和分享。欢送酷爱提高的你退出,兴许你的办法恰能解他人的当务之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官网技术博客:blog.uwa4d.com
官网问答社区:answer.uwa4d.com
UWA学堂:edu.uwa4d.com
官网技术QQ群:793972859(原群已满员)