0. 牢騷
我發(fā)現(xiàn)最仑,每個(gè)月的20+號(hào)是我有精力寫博客的時(shí)間……
這次項(xiàng)目算是經(jīng)歷的第一次嚴(yán)格意義上的渠道測(cè)試够挂,更換了正式名稱掉分,見(jiàn)了更多玩家逐虚,開(kāi)發(fā)組也經(jīng)歷的更多通宵……評(píng)價(jià)和數(shù)據(jù)如何暫時(shí)還未揭曉,趁著沒(méi)那么忙锯厢,來(lái)還欠自己的“文章債務(wù)”皮官。。实辑。
這篇博客主題是移動(dòng)平臺(tái)的天氣系統(tǒng)捺氢,做這個(gè)系統(tǒng)的主要原因是美術(shù)需求——大世界沙盤的動(dòng)態(tài)效果太少了,需要一些動(dòng)態(tài)變化的東西來(lái)增加效果剪撬。之前也看過(guò)一篇博客《Unity3D手游開(kāi)發(fā)日記(7) - 適合移動(dòng)平臺(tái)的天氣效果》摄乒,作者對(duì)于每種天氣效果大致聊了原理,我也挺感興趣婿奔,就在今天五一假期(是的缺狠,沒(méi)看錯(cuò),就是半年前的五一……)蹲在家里花了一天多時(shí)間照著文章的思路擼了一個(gè)簡(jiǎn)單版本萍摊,在加上之前積累的多云的效果,算是我們項(xiàng)目中天氣系統(tǒng)的雛形如叼。過(guò)了假期放出來(lái)給同事體驗(yàn)了下冰木,感覺(jué)還不錯(cuò),然后稍微修改了一些bug就被其他事情擱置下來(lái)了笼恰,所以7月份測(cè)試也沒(méi)有放出來(lái)踊沸。
7月技術(shù)測(cè)試之后,美術(shù)效果的增強(qiáng)也就被逐漸放到更高的優(yōu)先級(jí)社证,天氣系統(tǒng)也就成為了我的工作重點(diǎn)之一逼龟。經(jīng)歷整體結(jié)構(gòu)的重構(gòu)和一些效果實(shí)現(xiàn)方式的改變,才有了目前測(cè)試在用的這個(gè)版本追葡。本篇文章就以當(dāng)前已經(jīng)實(shí)現(xiàn)的幾種天氣效果為例來(lái)聊一下在移動(dòng)平臺(tái)上實(shí)現(xiàn)一套簡(jiǎn)單的天氣系統(tǒng)的思路和方法腺律。
1. 綜述
整體來(lái)說(shuō),移動(dòng)平臺(tái)的性能還不足以支撐端游上完整的一套天氣系統(tǒng)宜肉,Unity的Asset Store上有一些不錯(cuò)的天氣效果實(shí)現(xiàn)匀钧,也只能看著流流口水,并不敢用谬返,比如這個(gè)Weather Maker - Sky, Weather, Fog, Volumetric Light and Dynamic Environment之斯,還有UniStorm。(UniStorm有一個(gè)Mobile版本遣铝,效果也還不錯(cuò)佑刷,有興趣的同學(xué)可以去搜索看下莉擒。)
那么,在移動(dòng)端瘫絮,天氣系統(tǒng)效果簡(jiǎn)答來(lái)說(shuō)也就成了美術(shù)做做特效啰劲,程序按照需求寫寫掛特效的腳本罷了。的確檀何,在制作各個(gè)天氣的效果的時(shí)候蝇裤,并沒(méi)有用到什么特別的技術(shù)點(diǎn),但整個(gè)實(shí)現(xiàn)天氣系統(tǒng)的過(guò)程中频鉴,我沒(méi)有依賴于美術(shù)栓辜,而是自己尋找所有需要的資源,編寫邏輯進(jìn)行整合簡(jiǎn)化垛孔,過(guò)程還比較有趣藕甩,體會(huì)到非常直接的成就感,一些小的細(xì)節(jié)也自己去處理周荐,非常開(kāi)心狭莱。目前實(shí)現(xiàn)的天氣效果包括晴天、多云概作、陰天腋妙、雨天和雪天這幾種比較常見(jiàn)的效果,逐一來(lái)進(jìn)行說(shuō)明讯榕。
2. 晴天效果
我們項(xiàng)目中美術(shù)制作的所有場(chǎng)景都是按照晴天的效果來(lái)制作的骤素,所以對(duì)于程序來(lái)說(shuō),晴天效果就是沒(méi)效果愚屁,實(shí)現(xiàn)最簡(jiǎn)單济竹,性能最優(yōu),哈哈~(就是注意把其他效果清空不要?dú)埩簟?/p>
3. 多云效果
先看一下最終實(shí)現(xiàn)的多云效果截圖霎槐,動(dòng)態(tài)圖比較容易看出效果送浊,靜態(tài)圖感覺(jué)比較怪,可以注意主城的模型有一半是被云遮住了丘跌。為了凸顯效果云陰影的濃度被我故意調(diào)整得比較高袭景。
這個(gè)效果是之前美術(shù)想要的一個(gè)內(nèi)容。如果使用真正移動(dòng)一個(gè)半透的云模型在空中移動(dòng)并且產(chǎn)生投影碍岔,移動(dòng)設(shè)備上所能支持的shadowmap尺寸無(wú)法提供足夠的陰影精度浴讯,而直接進(jìn)行投影的方法又比較難做到在高低不平的山、建筑等物體表面計(jì)算投影效果蔼啦。經(jīng)過(guò)調(diào)研之后榆纽,使用了一個(gè)購(gòu)買的插件Screen Space Cloud Shadow。插件頁(yè)面有動(dòng)態(tài)效果視頻,想看動(dòng)態(tài)效果的可以去看下奈籽。當(dāng)時(shí)同樣調(diào)研了另外一個(gè)插件Cloud Shadows饥侵,都試玩了下。后者是基于light的cookie的衣屏,在當(dāng)時(shí)的unity版本中有些小問(wèn)題沒(méi)有解決掉躏升,而且我自己試驗(yàn)的cookie在移動(dòng)設(shè)備上有點(diǎn)小問(wèn)題,所以就沒(méi)有選用狼忱。Screen Space Cloud Shadow這個(gè)插件使用起來(lái)比較方便膨疏,只需要把prefab丟場(chǎng)景里就好,開(kāi)關(guān)也很簡(jiǎn)單钻弄,代價(jià)就是需要深度圖佃却,場(chǎng)景內(nèi)所有物件都要繪制兩遍,draw call和面數(shù)都會(huì)翻倍窘俺。這也是整個(gè)天氣系統(tǒng)中消耗最大的一塊饲帅,因此多云天氣在最終版本里也只有高配下才會(huì)開(kāi)啟。
由于是購(gòu)買的插件瘤泪,因此貼代碼不太合適灶泵,簡(jiǎn)單說(shuō)一下實(shí)現(xiàn)的原理:shader使用Transparent渲染隊(duì)列,在OnWillRenderObject中將一個(gè)平面放到相機(jī)的遠(yuǎn)平面对途,并且把尺寸縮放成和相機(jī)的遠(yuǎn)平面一樣赦邻,這樣就保證它的繪制過(guò)程是在最后,用FrameDebugger抓幀看繪制順序和參數(shù)如下圖:
在Shader的frag過(guò)程中掀宋,根據(jù)深度圖和世界空間的攝像機(jī)方向射線來(lái)計(jì)算出陰影應(yīng)該繪制的濃度深纲。這里包含了一些magic value,我也有些細(xì)節(jié)沒(méi)有看得特別懂……再加上本身并不是我自己設(shè)計(jì)的算法劲妙,因此不在這里詳述了,有興趣想了解的朋友可以自己去購(gòu)買一份插件儒喊,source code include镣奋。
這里只說(shuō)明三個(gè)遇到并解決的小坑:
- 由于云的陰影是飄動(dòng)的,因此涉及到uv的流動(dòng)怀愧,這個(gè)是根據(jù)時(shí)間來(lái)計(jì)算的侨颈,最初的時(shí)候這個(gè)時(shí)間直接取了
Time.time
的值,當(dāng)游戲運(yùn)行一段時(shí)間之后芯义,這個(gè)值就會(huì)變得很大哈垢,在移動(dòng)設(shè)備上會(huì)導(dǎo)致云的移動(dòng)出現(xiàn)頓卡的感覺(jué)。這也是在很多使用uv流動(dòng)的過(guò)程中很容易出現(xiàn)的一個(gè)問(wèn)題扛拨,通過(guò)取余的方式可以保證精度耘分,但是可能會(huì)在取余的那一幀出現(xiàn)采樣不連續(xù)的問(wèn)題。由于我們不會(huì)非常長(zhǎng)時(shí)間開(kāi)啟這個(gè)效果,因此這個(gè)問(wèn)題可以通過(guò)在開(kāi)關(guān)的時(shí)候把時(shí)間參數(shù)重置來(lái)規(guī)避求泰。 - fixed類型在移動(dòng)設(shè)備上精度問(wèn)題導(dǎo)致馬賽克央渣。原來(lái)Shader中使用了fixed的值,在PC上并沒(méi)有問(wèn)題渴频,安卓設(shè)備上發(fā)現(xiàn)了馬賽克的現(xiàn)象芽丹,修改幾個(gè)關(guān)鍵值為float類型可以解決馬賽克問(wèn)題。
- 由于使用了深度圖卜朗,因此深度圖的精度對(duì)于云的效果影響比較大拔第。我們最初相機(jī)的遠(yuǎn)平攝設(shè)置得非常遠(yuǎn),近平面又非常近场钉,0.1-1000這樣的值域范圍蚊俺。在PC上沒(méi)有問(wèn)題,手機(jī)上就有非常明顯的馬賽克惹悄,將近平面和遠(yuǎn)平面都調(diào)整一下春叫,變?yōu)?-300,效果好了很多泣港。(順便再推薦一下在UWA群里推薦過(guò)的調(diào)試插件暂殖,Hdg Remote Debug - Live Update Tool,可以在電腦上連接移動(dòng)設(shè)備進(jìn)行實(shí)時(shí)調(diào)試当纱,用于排查和調(diào)試這種問(wèn)題比頻繁打包要方便很多呛每,節(jié)省太多時(shí)間,已經(jīng)被我默認(rèn)打包進(jìn)了dev版本的工程里坡氯。)
4. 陰天
陰天的效果其實(shí)就是天色變暗的感覺(jué)晨横,如果是實(shí)時(shí)光照的話可以通過(guò)調(diào)暗方向光的亮度或者顏色來(lái)處理,但是由于手游上目前大都還是烘焙的箫柳,因此比較方便的方案就是通過(guò)后處理來(lái)實(shí)現(xiàn)手形。
考慮過(guò)Color Grading方案,但是感覺(jué)稍微有點(diǎn)耗悯恍,而且和晝夜系統(tǒng)實(shí)現(xiàn)會(huì)有些小沖突库糠,最后實(shí)現(xiàn)的時(shí)候選擇了直接在顏色上乘以一個(gè)Tint Color的方案來(lái)做,由于我們整合了整個(gè)后處理效果棧涮毫,因此在開(kāi)啟別的后處理的情況下瞬欧,這個(gè)tint color的過(guò)程消耗非常小,每個(gè)像素多一個(gè)乘法而已罢防。
這里也再推薦一下錢康來(lái)一直推薦的將所有的后處理Pass進(jìn)行整合的方案艘虎,也就是參考Unity官方的Github實(shí)現(xiàn):Post Processing Stack,Asset Store上也有Post Processing Stack咒吐。
5. 雨天
雨天的效果實(shí)現(xiàn)了兩個(gè)版本野建,最初的版本是基于前文提到的博客里的思路來(lái)實(shí)現(xiàn)的属划,就是掛一個(gè)uv流動(dòng)的面片在鏡頭前,閃電的效果就是把這個(gè)面片調(diào)整為白色再調(diào)整回來(lái)贬墩。實(shí)現(xiàn)非常簡(jiǎn)單榴嗅,這里只貼一下Shader代碼好了,因?yàn)闆](méi)有真正在項(xiàng)目中使用陶舞,所以只算私貨嗽测。
Shader "Shader/Scene/Rain" {
Properties{
_RainTex("Main Texture:", 2D) = "white" {}
_RainIntensity("Intensity of Rain:",Float) = 0.0
_FallSpeed("Fall Speed of Rain:",Float) = 1
_ThunderLighting("Thunder Lighting", Color) = (0, 0, 0, 0.5)
}
SubShader{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
Blend SrcAlpha One
LOD 100
Cull Off
ZWRITE Off
Lighting Off
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#include "UnityCG.cginc"
sampler2D _RainTex;
float4 _RainTex_ST;
fixed _FallSpeed;
fixed _RainIntensity;
float4 _ThunderLighting;
struct appdata_t {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.texcoord = TRANSFORM_TEX(v.texcoord, _RainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed2 UV = i.texcoord;
float Time = _Time.y;
fixed vValue = _FallSpeed * Time;
UV = fixed2(UV.x, UV.y + _FallSpeed * Time);
fixed4 col = tex2D(_RainTex, UV);
col.rgb = col.rgb * col.a * _RainIntensity + _ThunderLighting.rgb;
col.a = 1.0f;
return col;
}
ENDCG
}
}
}
實(shí)現(xiàn)的效果截圖如下圖所示。鏡頭前的面片使用的貼圖也是我從網(wǎng)上找的雨滴噪聲貼圖自己修改的肿孵,因此有不連續(xù)的問(wèn)題唠粥,截圖中可以看出來(lái),這個(gè)也是自己P圖的基本功不夠的原因……
這里學(xué)習(xí)到一個(gè)小的技巧是可以使用Unity的AnimationCurve
來(lái)做一些曲線供游戲邏輯使用停做,從而做出來(lái)一些變化的效果晤愧,這里就用曲線控制了雨的濃度和與雷聲配合的閃電效果,C#代碼也貼一下蛉腌。
using UnityEngine;
namespace ThorFramework.Weather
{
[DisallowMultipleComponent]
public class RainController : MonoBehaviour
{
public AnimationCurve rainCurve;
public AnimationCurve thunderCurve;
private Color lightingColor = Color.white;
private Material weatherMaterial;
private float startTime = 0.0f;
private AudioSource thunderAudio;
// Use this for initialization
void Start()
{
MeshRenderer r = gameObject.GetComponent<MeshRenderer>();
if (r != null)
{
weatherMaterial = r.material;
startTime = Time.time;
}
thunderAudio = gameObject.GetComponent<AudioSource>();
}
void OnEnable()
{
startTime = Time.time;
}
// Update is called once per frame
void Update()
{
float curveTime = Time.time - startTime;
if (weatherMaterial == null)
{
return;
}
if (rainCurve != null)
{
float val = rainCurve.Evaluate(curveTime);
weatherMaterial.SetFloat("_RainIntensity", val);
thunderAudio.volume = 2.0f * val;
}
if (thunderCurve != null)
{
float val = thunderCurve.Evaluate(curveTime);
weatherMaterial.SetColor("_ThunderLighting", lightingColor*val);
}
}
}
}
這種實(shí)現(xiàn)OverDraw會(huì)直接翻倍官份,但是沒(méi)有其他的太多額外消耗,因此性能上還比較節(jié)省烙丛,大致測(cè)試了下對(duì)于性能幾乎感受不出來(lái)影響舅巷,特別是被降低了分辨率的情況下。但是最終我們還是沒(méi)有采用這種方案河咽,主要原因是這種效果很難做出深度感钠右,就是雨滴真的在空間中有分布的感覺(jué)。最終還是用了粒子特效忘蟹,一個(gè)一直掛在相機(jī)前的特效飒房,在區(qū)域范圍內(nèi)一直產(chǎn)生垂直墜落的雨滴。
在這之前我沒(méi)怎么玩過(guò)粒子系統(tǒng)媚值,這里從頭學(xué)習(xí)制作一個(gè)粒子特效狠毯,還是挺有趣的。粒子系統(tǒng)可以用比較簡(jiǎn)單的方法制作出非橙烀ⅲ酷炫的效果垃你。最終實(shí)現(xiàn)效果的截圖如下:
這里雨的效果包括三個(gè)部分:
- 跟隨相機(jī)移動(dòng)的一個(gè)產(chǎn)生雨滴的特效,截圖中雨滴不是很密集喂很,但是動(dòng)起來(lái)的效果還是不錯(cuò)的。這里為了追求效果粒子數(shù)量上限給到了500左右皆刺,但是仍然不是非常密集少辣,做不到暴風(fēng)雨的感覺(jué),還需要添加一些面片來(lái)做更加密集的雨滴效果羡蛾。
- 跟隨角色移動(dòng)的地面漣漪漓帅。在通常的做法中,雨滴漣漪的制作是用粒子系統(tǒng)的碰撞來(lái)做的。當(dāng)粒子產(chǎn)生了碰撞之后就會(huì)產(chǎn)生一個(gè)新的粒子效果忙干,這樣可以做到很精準(zhǔn)的感覺(jué)器予,包括落在樹(shù)葉上、建筑房頂上等捐迫,但是消耗也比較大乾翔。我們采用的是比較討巧的方法,角色腳底掛一個(gè)不斷隨機(jī)產(chǎn)生漣漪的粒子特效施戴,在斜坡反浓、橋上等地方會(huì)有穿幫的小問(wèn)題,但是也基本滿足的策劃的需求赞哗。
- 與陰天一樣雷则,下雨的時(shí)候會(huì)陰暗一些,所以同樣掛了一個(gè)tint color調(diào)色的后處理肪笋。
總結(jié):雨的效果花費(fèi)了挺多精力來(lái)制作月劈,最終的效果基本滿意。使用特效的方案整體的overdraw沒(méi)有那么高藤乙,但是為了出效果粒子數(shù)量用得還算比較多猜揪,因此在粒子系統(tǒng)上的性能消耗還挺大的。對(duì)比之前面片的方案各有優(yōu)劣湾盒,只是出了追求高品質(zhì)效果的考慮選擇了效果上限較高的粒子系統(tǒng)來(lái)實(shí)現(xiàn)湿右。
6. 雪天
在實(shí)現(xiàn)雨天的效果之后,雪天的效果制作就非常簡(jiǎn)單了罚勾,霧效果加上一個(gè)和雨滴相似的粒子特效掛在鏡頭前就可以啦毅人。由于雪花生命周期比較長(zhǎng),飄落速度比較慢尖殃,粒子數(shù)最多在300左右就可以達(dá)到不錯(cuò)的效果丈莺。實(shí)現(xiàn)的效果截圖如下(這里有一些序列幀動(dòng)畫之類的小技巧可以優(yōu)化雪片的效果,不過(guò)不屬于程序的技術(shù)了送丰,特效同學(xué)應(yīng)該都會(huì)的):
也同樣研究了一下《鎮(zhèn)魔曲》中雪花效果的實(shí)現(xiàn)缔俄,發(fā)現(xiàn)比較討巧的是他們沒(méi)有讓一個(gè)雪花是一個(gè)粒子,而是用一張圖來(lái)表現(xiàn)幾片雪花的效果器躏,然后大約只需要同時(shí)存在十幾個(gè)粒子就可以做到比較密集的下雪效果俐载。當(dāng)然代價(jià)是仔細(xì)觀察的話會(huì)發(fā)現(xiàn)一些重復(fù)感,overdraw也會(huì)稍微有些提高登失,但是粒子數(shù)量降低得會(huì)比較多遏佣,值得借鑒。(我們美術(shù)同學(xué)嘗試了一個(gè)版本之后告訴我不太滿意揽浙,當(dāng)然在看了完全隨機(jī)的效果之后状婶,對(duì)于略有重復(fù)的效果自然能感覺(jué)出來(lái)瑕疵意敛,沒(méi)有對(duì)比才沒(méi)有傷害……)
7. 風(fēng)
風(fēng)不屬于任何一個(gè)天氣,而是用于輔助表現(xiàn)其他天氣效果的元素膛虫,在我們游戲中主要能做的表現(xiàn)是樹(shù)木的搖擺和一些相應(yīng)的音效草姻。搖擺的效果采用頂點(diǎn)動(dòng)畫來(lái)實(shí)現(xiàn),已有的實(shí)現(xiàn)方案可以參考Unity3D手游開(kāi)發(fā)日記(5) - 適合移動(dòng)平臺(tái)的植被隨風(fēng)擺動(dòng)這篇文章稍刀,網(wǎng)上也有很多實(shí)現(xiàn)細(xì)節(jié)的討論撩独,但比較好的方案追本溯源還是《GPU Gems》中的一篇文章:《Chapter 16. Vegetation Procedural Animation and Shading in Crysis》。它主要描述了在CryEngine中的實(shí)現(xiàn)原理掉丽,考慮到樹(shù)干和樹(shù)葉的不同跌榔,使用頂點(diǎn)色來(lái)對(duì)振幅進(jìn)行控制,估計(jì)很多人都讀過(guò)捶障,實(shí)現(xiàn)細(xì)節(jié)可以去參考原文僧须。
這里只說(shuō)幾個(gè)我們移植時(shí)的幾個(gè)修改:
- 使用Shader的全局變量。Shader.SetGlobalXXX一系列的接口就是為這種全局參數(shù)來(lái)設(shè)計(jì)的项炼,簡(jiǎn)單易用担平。
- 臨近測(cè)試我們美術(shù)比較忙,表示沒(méi)時(shí)間對(duì)每棵樹(shù)的模型去刷頂點(diǎn)色锭部,于是搖擺的幅度控制采用了一個(gè)簡(jiǎn)化的方案——由頂點(diǎn)高度和一個(gè)美術(shù)設(shè)定的模型高度的比值來(lái)決定暂论,目前只采用的線性差值,效果一般拌禾,勉強(qiáng)夠用取胎。
- GPU Gem中的實(shí)現(xiàn)比較復(fù)雜,考慮了橫向的和縱向的抖動(dòng)湃窍,有不少計(jì)算在里面闻蛀,這塊可以根據(jù)自己項(xiàng)目的游戲類型和需求來(lái)修改和簡(jiǎn)化。
8. 整合
把實(shí)現(xiàn)的各個(gè)天氣效果整合成天氣系統(tǒng)您市,由一個(gè)管理器來(lái)控制觉痛,可以模擬游戲中各個(gè)國(guó)家的氣候風(fēng)格,這是最后整合進(jìn)游戲進(jìn)行實(shí)際應(yīng)用的步驟茵休。由于我們大世界和戰(zhàn)斗場(chǎng)景是兩種完全不同的鏡頭方式薪棒,因此最終特效掛接的部分實(shí)現(xiàn)了兩套不同的控制邏輯。除此之外榕莺,根據(jù)不同國(guó)家的特性俐芯,也將雨天和雪天統(tǒng)一為了特殊天氣,比如在燕國(guó)這樣靠北的國(guó)家钉鸯,就只會(huì)下雪泼各,而其他國(guó)家則是下雨。這其中有很多繁雜的與游戲業(yè)務(wù)相關(guān)的邏輯就不談了亏拉,只聊幾個(gè)實(shí)現(xiàn)過(guò)程中比較有感觸的點(diǎn):
- 漸變需求扣蜻。天氣效果中所有的控制效果都有不同的漸變細(xì)節(jié)需要處理,比如下雪天氣停止不能突然沒(méi)有及塘,而是要有漸漸消失的感覺(jué)莽使;天氣由晴天變陰天,也不應(yīng)該突然黑下來(lái)笙僚,而是要有一個(gè)亮度漸變的過(guò)程芳肌。這些需要各個(gè)天氣系統(tǒng)針對(duì)自己的效果做好差值的處理,這個(gè)過(guò)程使用了DoTween來(lái)做肋层,代碼實(shí)現(xiàn)非常簡(jiǎn)單高效亿笤。
-
對(duì)于需要跨天氣控制的效果進(jìn)行統(tǒng)一的管理。在最初的版本里栋猖,用于表現(xiàn)變暗效果的Tint Color由每一個(gè)天氣進(jìn)行各自的管理和差值净薛,這里就有一些非常惡心的特殊代碼要做處理,比如陰天效果的停止函數(shù)中蒲拉,當(dāng)進(jìn)入晴天的時(shí)候需要把亮度逐漸調(diào)整到1肃拜,如果從陰天進(jìn)入雨天,則不需要做這樣的調(diào)整雌团。天氣效果的控制也就像是一個(gè)狀態(tài)機(jī)燃领,在單獨(dú)的狀態(tài)中如果需要考慮變換的前后邏輯,代碼里就需要非常多if-else這樣的邏輯判斷锦援。在迭代的過(guò)程中猛蔽,把這塊的控制抽象成為一個(gè)天氣亮度管理器——
BrightnessManager
,它負(fù)責(zé)控制亮度并按照設(shè)定的速度在當(dāng)前亮度和目標(biāo)亮度之間做差值灵寺,這樣對(duì)于任何天氣效果曼库,只需要在開(kāi)啟的時(shí)候設(shè)置默認(rèn)的亮度值給亮度管理器,其他細(xì)節(jié)都不需要關(guān)心替久。同樣還有用于風(fēng)的參數(shù)控制的WindManager凉泄。 - 效果與實(shí)現(xiàn)邏輯的分離。從表面上看蚯根,下雨和下雪是兩個(gè)不同的天氣效果后众,但是他們?cè)诔绦虻倪壿嬍怯泻艽笙嗨菩缘摹际强刂铺匦У膾旖雍透S邏輯。因此從邏輯實(shí)現(xiàn)上這兩個(gè)天氣效果有相同的邏輯颅拦,只是數(shù)據(jù)(特效)不同而已蒂誉。另外下雨的效果有額外的一些漣漪的處理。于是使用面向?qū)ο蟮乃悸烦槿∫粋€(gè)FXWeather的公共父類來(lái)做代碼的復(fù)用距帅,方便維護(hù)右锨。
經(jīng)過(guò)一些思考和迭代之后,最終C#代碼中的類圖如下所示碌秸。
9. 總結(jié)
回顧整個(gè)天氣系統(tǒng)的實(shí)現(xiàn)绍移,其實(shí)沒(méi)有特別有難度的東西悄窃,只是一些效果的應(yīng)用和業(yè)務(wù)邏輯的編寫。使用面向?qū)ο蟮睦^承和組合蹂窖,再加上狀態(tài)模式就完成了最后的需求轧抗。在效果方面,由于要兼顧移動(dòng)平臺(tái)的性能限制瞬测,相比端游的動(dòng)態(tài)天氣效果做了很多妥協(xié)和簡(jiǎn)化横媚,盡量用20%的性能消耗做到60%的表現(xiàn)力,對(duì)于真實(shí)感等方面做了不少的妥協(xié)月趟。
當(dāng)然灯蝴,現(xiàn)在實(shí)現(xiàn)的各種天氣效果還很簡(jiǎn)陋,比如下雨還可以添加地面濕滑的材質(zhì)效果孝宗,還可以制作暴風(fēng)雨這樣更動(dòng)感刺激的天氣效果穷躁,在沙漠中實(shí)現(xiàn)沙塵暴的感覺(jué)等等。這些東西碳褒,還需要更多的時(shí)間和精力來(lái)填滿缺失的細(xì)節(jié)折砸。
無(wú)論如何,希望這篇文章可以給期望增強(qiáng)游戲效果的同學(xué)一些啟發(fā)沙峻,也同樣期望有更好實(shí)現(xiàn)效果和方法的朋友不吝賜教睦授,給予更多思路和經(jīng)驗(yàn)的分享。
2017年9月26日凌晨 于杭州家中