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);