1)Unity场景物体动静合批2)Unity内置音频Android平台播放提早问题3)对Unity Package中的Shader打包防止冗余的计划4)UnityEditor PropertyField并排显示谬误
这是第307篇UWA技术常识分享的推送。明天咱们持续为大家精选了若干和开发、优化相干的问题,倡议浏览工夫10分钟,认真读完必有播种。
UWA 问答社区:answer.uwa4d.comUWA QQ群2:793972859(原群已满员)
RenderingQ1:问题1:为了能使场景中物体合批(同材质球),场景在制作的时候雷同的预制体放在了一起,然而FrameDebug看到的却是乱序。请问在这个Frame里的程序是如何定义能力达到雷同的合批?也就是如何能起码化的Objects have different materials?
问题2:在FrameDebug高低排列且雷同物体,仍然没有合批。给出的起因是“Objects are lightmapped”。网上给出的解释是应用了不同的光照贴图(这里是一样的),或在雷同的光照贴图中由不同的光照贴图UV转换关系。这个转换关系是什么意思?是UV对应的Offset几个参数必须要一样么?然而物体在不同的地位,实践上肯定会不一样。请问这个要怎么解决?目前场景中物体占用了120个DrawCall,想尽可能优化。
A:第一个问题,针对不通明物体,Unity默认由近往远绘制(离相机的间隔),所以如果想要雷同的材质球是间断绘制的,能够通过调整RenderQueue来强行间断绘制,不过可能会导致渲染成果不合乎预期(遮挡关系错乱),另外的害处是会毁坏Early-Z的性能,尤其在没有HSR性能的低端机上,Overdraw会造成高复杂度的Shader带来的GPU高压力,所以须要衡量CPU提交Batch的耗时和GPU的压力。
第二个问题,同类型材质球(Shader一样,变体也一样),如果Lightmap index不一样(也就是Lightmap不一样),必定是不能合批的(SRP Batcher除外,SRP Batch忽视材质球,只有Shader和变体一样就能够)。在Lightmap雷同的状况下,如果对应的unity_LightmapST不一样,也是不能合批的。这里有两种办法解决,一种是用Static Batching,这样会让unity_LightmapST变成同一种,具体的UV会变成顶点数据(原本子Mesh的UV都是(0,1)的,合并Combined Mesh后会变成相似于(0.3,0.5)这样的区间),就是说顶点外面的UV原本存储的是Local空间的,变成Combined Mesh后,合体的Mesh数据外面存储的是World空间的,这样外在的unity_LightmapST对于不同的子Mesh就会变成共用的(1,1,0,0)这样的独特属性,也就能够合批了。另外一种是开启GPU Instancing,这样unity_LightmapST会变成CBuffer,这样也是会合批的。
如下图所示,Cube1和Cube2在FrameDebugger的惟一区别就是unity_LightmapST不一样,所以不开启GPU Instancing和Static Batching的状况下,是不能合批的,尽管它们是相邻的绘制程序,Lightmap也是雷同的。另外两个Cube(1)和Cube别离用的Lightmap2和Lightmap0。
开启动态合批后,两头的2个Cube合成了一个Batch,它们的unity_LightmapST变成了独特的(1,1,0,0),如下图:
材质球勾选GPU Instancing后,在FrameDebugger面板外面,曾经看不到unity_LightmapST这个属性了。这两个Cube也是合成了一个Instanced Batch。如下图:
感激Xuan@UWA问答社区提供了答复
Q2:对于第二个问题的解决办法。因为咱们是动态创建物体。所以无奈用动态合批。当我尝试应用GPU Instancing 后,批次简直没变,一种是咱们的不同的Mesh,应用同一个材质球,无奈合批;其次是同一个Mesh也无奈合批。如下提醒:
另外仍然还有“Objects are lightmaped”的提醒,且曾经没有Lightmap_ST,材质球都已勾选GPU:
还有Shader是有两个PASS的。是否另一个PASS也须要退出GPU Instancing 的代码?附Shader代码:
Shader "WF/SceneObj"{ Properties { [NoScaleOffset]_MainTex("主贴图 (RGBA)", 2D) = "white" {} [Space(20)] _OutlineWidth("描边宽度", Range(0, 0.5)) = 0.018 _OutlineColor("描边色彩", Color) = (0, 0, 0, 1) [Space(20)] _EmissionMask("自发光遮罩 (G)", Range(0, 5)) = 1 [HDR]_EmissionColor("自发光色彩", Color) = (1, 1, 1, 1) _Color("Color", Color) = (1, 1, 1, 1) } SubShader { Tags{ "RenderType" = "Opaque" "Queue" = "Geometry+1" } // lightmap Pass { Tags { "LightMode" = "ForwardBase" } CGPROGRAM #pragma multi_compile_fwdbase #pragma multi_compile_instancing #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" #include "AutoLight.cginc" #pragma multi_compile_fog #define USING_FOG (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)) struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; float2 texcoord : TEXCOORD0; float3 uv1 : TEXCOORD1; // lightmap UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float2 uv1 : TEXCOORD2; half3 worldlight : TEXCOORD1;#if USING_FOG fixed fog : TEXCOORD3;#endif UNITY_VERTEX_OUTPUT_STEREO UNITY_VERTEX_INPUT_INSTANCE_ID }; sampler2D _MainTex; float4 _MainTex_ST; float _EmissionMask; fixed4 _EmissionColor; UNITY_INSTANCING_BUFFER_START(Props) UNITY_DEFINE_INSTANCED_PROP(float4, _Color) UNITY_INSTANCING_BUFFER_END(Props) v2f vert(a2v v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); UNITY_TRANSFER_INSTANCE_ID(v, o); o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); // o.worldlight = UnityObjectToViewPos(v.normal); o.uv1 = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw; // fog#if USING_FOG float3 eyePos = UnityObjectToViewPos(v.vertex); float fogCoord = length(eyePos.xyz); // radial fog distance UNITY_CALC_FOG_FACTOR_RAW(fogCoord); o.fog = saturate(unityFogFactor);#endif return o; } fixed4 frag(v2f i) : SV_Target { UNITY_SETUP_INSTANCE_ID(i); fixed4 originalCol = tex2D(_MainTex, i.uv) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color); ////------------------------------漫反射------------------------------ //-----------------------------------自发光 //float emission = originalCol.a * _EmissionMask; //自发光 //float emisstionValue = emission < 0.5 ? 0 : 1; fixed3 emisstionCol = originalCol.rgb * _EmissionColor.rgb * _EmissionMask; // //叠加 fixed3 finnalCol = originalCol; fixed4 col = (fixed4)1;#if defined(LIGHTMAP_ON) // half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1.xy); col.rgb = DecodeLightmap(bakedColorTex);#endif finnalCol = lerp(finnalCol, emisstionCol, originalCol.a) * col.rgb; // fog#if USING_FOG finnalCol.rgb = lerp(unity_FogColor.rgb, finnalCol.rgb, i.fog);#endif return fixed4(finnalCol, 1); } ENDCG } Pass { NAME "OUTLINE" Cull Front CGPROGRAM #pragma multi_compile_fog #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct a2v { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; UNITY_FOG_COORDS(0) }; sampler2D _MainTex; float4 _MainTex_ST; fixed4 _OutlineColor; float _OutlineWidth; v2f vert(a2v v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); float3 viewNormal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal); float2 ndcNormal = normalize(TransformViewToProjection(viewNormal.xy)) * pow(o.pos.w, 0.6) * 2; float4 nearUpperRight = mul(unity_CameraInvProjection, float4(1, 1, UNITY_NEAR_CLIP_VALUE, _ProjectionParams.y)); float aspect = abs(nearUpperRight.y / nearUpperRight.x); ndcNormal.x *= aspect; o.pos.xy += ndcNormal * _OutlineWidth * 0.1; UNITY_TRANSFER_FOG(o,o.pos); return o; } fixed4 frag(v2f i) : SV_Target { fixed3 col = _OutlineColor.rgb ; return fixed4(col, 0); } ENDCG } } Fallback "Diffuse"A:动态创建物体的动态合批的办法能够参考StaticBatchingUtility.Combine的API,这是一项运行时动态合批的做法;其次如果应用了多个Pass的Shader,想要应用GPU Instancing进行合批,每个Pass都要设置成GPU Instancing能力失常合批。感激宗卉轩@UWA问答社区提供了答复
...