unity优化一些总结 (长期更新)
UI:
1:尽量不要使用动态文本
2: 使用更多画布 拆分画布
我开始使用3幅画布。一个用于我的背景图像,一个用于我的主要UI元素,另一个用于需要放置在其他所有元素顶部的元素。
我了解到,每当画布中的某些内容发生变化时,整个画布都会被重新评估并重新绘制。因此,除了最简单的UI之外,将UI分成多个画布的好处可能非常重要。即使对于简单的HUD,将其拆分为用于静态元素的画布和用于动态元素的画布也可能要快得多。
缺点是每个画布都会增加绘制调用。因此,在决定拆分画布时,我们仍需要平衡速度以提高效率。
3: 禁用不可见的UI,擅长使用RectMask 2D
我有很多UI屏幕移入和移出摄像机视图,所有这些都有助于绘制调用。有时我可以禁用游戏对象,但是同样会产生性能问题。也可以移除屏幕外,但问题是所有这些活动的UI元素仍然被计算并添加到绘制调用中,即使它们没有被看到。
Unity提出了一些可以处理的方法,但是有一个非常简单的解决方案,在这种情况下没有提到,它本身做得很好,而且当与其他策略结合时甚至更好。在Unity 5.2中引入,它是Rect Mask 2D
。
掩盖你的用户界面
将一个Rect Mask 2D
组件放在主画布上。
4: 简化UI着色器
我了解到UI Default
着色器非常灵活,但对于许多元素来说都是过度杀伤。UI Fast-Default
当我们不需要花哨的东西时,在帖子中提供的着色器(由于某种原因而不是应用程序)是一个更快的使用。
Shader "UI/Fast-Default"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
}
SubShader
{
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Cull Off
Lighting Off
ZWrite Off
ZTest [unity_GUIZTestMode]
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "UnityUI.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
float4 worldPosition : TEXCOORD1;
};
fixed4 _Color;
fixed4 _TextureSampleAdd;
v2f vert(appdata_t IN)
{
v2f OUT;
OUT.worldPosition = IN.vertex;
OUT.vertex = mul(UNITY_MATRIX_MVP, OUT.worldPosition);
OUT.texcoord = IN.texcoord;
#ifdef UNITY_HALF_TEXEL_OFFSET
OUT.vertex.xy += (_ScreenParams.zw-1.0)*float2(-1,1);
#endif
OUT.color = IN.color * _Color;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
return (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
}
ENDCG
}
}
}
5: 不要使用默认的滚动视图
除了我关于UI着色器的问题之外,我一直在质疑默认UI对象的效率,特别是在了解了Rect Mask 2D
比标准更好的情况之后UI Mask
。为什么不是默认Scroll View
使用Rect Mask 2D
?这对其他默认UI对象意味着什么?
6: 屏幕遮罩处理,阻挡点击穿透,使用文本Text
我们在整个屏幕上处理触摸时做的第一件事(做弹出逻辑和/或阻止所有其他画布)是使用没有Sprite设置的图像,并且启用raycast。工作正常,但它造成的性能问题却是不可逃避的,而且还为所有屏幕渲染了一个大的空透明四边形,这在移动设备上非常糟糕。
我们的解决方案是更改为使用文本,也扩展到所有屏幕但没有字体或文本集。它不消耗渲染时间(在移动设备上测试)并按预期处理光线投射,我想这是因为它不生成网格(因为它没有文本或字体集)并且同时仍然有配置的光线投射的边界框。
6::Material/Animator/Shader属性访问
永远不要直接通过名字去访问,因为在引擎内部需要对字符串名字计算哈希得到一个整数id~错误做法
material.SetColor("_Color", Color.white);
animator.SetTrigger("attack");
正确做法是一开始启动的时候计算一次哈希,然后缓存下来…
static readonly int material_Color = Shader.PropertyToID("_Color");
static readonly int anim_Attack = Animator.StringToHash("attack");
material.SetColor(material_Color, Color.white);
animator.SetTrigger(anim_Attack);