共计 3365 个字符,预计需要花费 9 分钟才能阅读完成。
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(原群已满员)