用Unity重現(xiàn)《空洞騎士》的苦痛之路(4)——完結(jié)篇

作者:繁華如夢
前言:
終于來到本系列的最后一篇,感覺整個人都快肝廢了。本來想鴿的,最終憑著最后一點肝續(xù)了下來。

在之前的篇章中,我們已經(jīng)完成游戲主體的搭建。接下來只需要添加上對應(yīng)的特效,就能夠使整個游戲變得更加完整。(PS:本期中代碼并沒有過多講解且并不完整,說得最多的是思路,還請留意)
超級沖刺特效
超級沖刺的特效大致是由4種特效組合來完成的,分別是:
1.沖刺特效
2.聚集特效
3.聚集完成特效
4.地面水晶
在上面的的特效中,某一部分由于找不到對應(yīng)的圖片,將不會與原版一樣,而且其中還有與人物動畫進行配合的部分,將不會實現(xiàn)類似的細節(jié)。還請各位童鞋留意。
聚集與沖刺特效
聚集狀態(tài)與沖刺狀態(tài)下的特效,都是使用的幀動畫來進行制作的。在合適的地方播放該幀動畫即可。此處就不在多說了。
聚集完成特效
聚集完成的特效,由于缺少相關(guān)的序列幀,此處只能自己搭建圖像來近似相關(guān)的圖像以及動畫。流程就是,先參照原版游戲特效畫面,自己通過游戲素材搭建出一幀幀畫面,并通過代碼控制物體的顯示,來模擬出相應(yīng)的效果。(還好這個只有4幀,多了我還真的吃不消)大致幀序列如下:

(盜文章的人實在是太多了,不知道加水印是否有用)
地面水晶
在超級沖刺的時候,地面會隨時間向上生成紫色的水晶,并向周圍擴散生成。其中有一個小細節(jié),就是水晶只會生成在地面,在空中不會進行生成。此處,我們偷一下懶,水晶并不是動態(tài)生成,而是一開始搭建好的,然后在需要生成的時候,通過朝地面打射線的方式判斷是否在地面,來決定是否顯示水晶。如下圖:

特效組合后效果如下:

代碼大致如下。其中考慮到在墻上的超級沖刺,需要事先設(shè)定好轉(zhuǎn)向的旋轉(zhuǎn)信息,防止動態(tài)修改出現(xiàn)誤差:
??? Quaternion leftQua;???????????????? //超級沖刺特效地面水晶在墻上的旋轉(zhuǎn)
??? Quaternion rightQua;
??? GameObject particleObj;???? //超級沖刺物體(紫色水晶)
??? void Start()
??? {
??????? particleObj.transform.Rotate(new Vector3(0, 0, -90));//初始化左右旋轉(zhuǎn)后的四元素,用于后面特效轉(zhuǎn)向
??????? leftQua = particleObj.transform.rotation;
??????? particleObj.transform.Rotate(new Vector3(0, 0, 180));
??????? rightQua = particleObj.transform.rotation;
??????? particleObj.transform.Rotate(new Vector3(0, 0, -90));
??? }
??? public void SuperSprintFunc()
??? {
? ??????if (Input.GetKeyDown(InputManager.Instance.superKey))
??????? {
??????????? ....
??????? }
??????? else if (Input.GetKey(InputManager.Instance.superKey))
??????? {
??????????? ....
??????????? LookParticObj();
??????? }
??? }
??? public void LookParticObj()
??? {
??????? GameObject tempObj = particleObjs[lookLevel];//particleObjs 數(shù)組存儲所有的特效(水晶)物體
??????? SpriteRenderer[] renderers = tempObj.GetComponentsInChildren<SpriteRenderer>(true);
??????? for (int i=0;i<renderers.Length;i++)
??????? {
?? ?????????ParticObjIsLook(renderers[i].transform);
??????? }
??? }
??? public bool ParticObjIsLook(Transform objTrs)
??? {
??????? RaycastHit2D hit2D;
??????? if (isClimb)??????? //如果進行了爬墻狀態(tài) 射線發(fā)射方向改變
??????? {
??????????? if (nowDir == PlayDir.Right)
????? ??????{
??????????????? hit2D = Physics2D.Raycast(objTrs.position, Vector3.right, boxSize.y, playerLayerMask);
??????????? }
??????????? else
??????????? {
??????????????? hit2D = Physics2D.Raycast(objTrs.position, Vector3.left, boxSize.y, playerLayerMask);
??????????? }
??????? }
??????? else
??????? {
??????????? hit2D = Physics2D.Raycast(objTrs.position, Vector3.down, boxSize.y, playerLayerMask);
??????? }
??????? if (hit2D.transform!=null)
??????? {
??????????? objTrs.gameObject.SetActive(true);
?????? ?????return true;
??????? }
??????? objTrs.gameObject.SetActive(false);
??????? return false;
??? }
?
二段跳特效
二段跳特效也是使用2種特效來組合完成的。分別是二段跳的翅膀光翼,以及落下的羽毛特效。光翼沒有對應(yīng)的素材,此處直接跳過。只使用Unity的粒子系統(tǒng)來制作與羽毛落下的效果。
制作特效前,首先先找到對應(yīng)的羽毛圖片,如下:(注:此處圖片是我在PS中切出來的3張單獨的圖片。)

然后為3張不同的羽毛新建不同的材質(zhì)。之后在著色器選項中,選擇Particles/Additive,再在后續(xù)的選項選擇素材羽毛圖片即可。雖然2D的精靈圖應(yīng)該是使用著色器Sprites/Default,但是我們這里選擇粒子特效的著色器,效果更好(PS:著色器可以自由選擇,你覺得好看就行)。如下圖:

接下來新建一個空物體,并添加上粒子系統(tǒng)組件(Particle System),在Renderer(渲染)模塊下的material選項,選擇我們創(chuàng)建好的材質(zhì)。如下圖:

在這里簡單說一下我們會用到的屬性。
Duration(粒子發(fā)射的持續(xù)時間)
Start Lifetime(粒子的存活時間)
Start Speed(粒子的速度)
Gravity Modifier(重力修正,可以理解為重力的倍數(shù))

Emission(發(fā)射模塊)
Rate over Time(單位的時間發(fā)出的粒子數(shù))
Rate over Distance(單位的移動距離發(fā)出的粒子數(shù))

Shape (形狀模塊)
Shape(粒子發(fā)射的形狀)
Radius(半徑)

Size over Lifetime(粒子大小隨時間變化模塊)
Separate Axes(勾選該選項,分開處理3軸屬性)
Size(調(diào)整對應(yīng)屬性,粒子的大小在生命周期內(nèi)會按照曲線進行變化)

Rotation Over Lifetime(粒子旋轉(zhuǎn)隨時間變化模塊)
Separate Axes(勾選該選項,分開處理3軸屬性)
Angular velocity(角速度)(PS:由于是2d物體,此處只需要繞Z軸的旋轉(zhuǎn)速度)

值得注意的是,上面的選項除了Duration,其余都是支持自定義曲線模式,來編輯粒子系統(tǒng)播放時數(shù)值隨時間的變化。如下圖:

接下來就是根據(jù)羽毛特效,來調(diào)整對應(yīng)的參數(shù)了。(PS:上面的模塊截圖屬性就是我使用的)由于上面的大部分屬性都是使用了曲線模式來進行編輯的,這些參數(shù)根據(jù)自己的理解來進行設(shè)置即可。同時,為了羽毛特效的形態(tài)不同,我們還需要在為其余的2張不同形態(tài)的羽毛制作2個粒子特效,并將這3個特效制作為一個預(yù)制體,來完成這一效果!完成后如下圖:

暗影沖刺特效
拖尾粒子
在進行暗影沖刺的時候,玩家身后會出現(xiàn)一條由黑色小圓點組成的拖尾。本質(zhì)是一個拖尾粒子。制作同上,素材只需要一張黑色的小圓點圖片,只不過不需要隨時間進行粒子的生成,而是隨移動距離來生成粒子。即Rate over Time數(shù)值為0,Rate over Distance數(shù)值按需調(diào)整即可。由于是圓形粒子,跟隨時間的旋轉(zhuǎn)也可以取消。完成后如下圖:

然后就是在代碼中,暗影沖刺開始時生成對應(yīng)的特效物體,讓特效物體隨玩家進行移動,在暗影沖刺結(jié)束時停止跟隨,并在一段時間后銷毀特效物體。代碼比較簡單,這里就不在貼出了。
拖尾與回復(fù)動畫
在播放暗影沖刺動畫時,還附帶有拖尾的幀動畫,以及暗影沖刺能量回復(fù)的幀動畫。一開始制作好相應(yīng)的幀動畫物體,并放在玩家的節(jié)點下,在沖刺開始以及結(jié)束的時候播放對應(yīng)動畫即可。動畫如下:

暗影沖刺動畫
在原作中,暗影沖刺在地上進行沖刺,與在空中進行沖刺略有不用。需要在播放動畫時,進行判斷,此處需要注意!動作如下:

特效物體組合后效果如下:

攻擊交互特效
玩家攻擊到不同的物體將會有不同的特效提示,此處摸一下魚,只制作攻擊碰撞到陷阱的交互特效。
仍然先將特效的幀動畫制作出來。如下:

然后在代碼中,攻擊檢測時進行生成對應(yīng)的幀動畫物體。需要注意的是,不同的攻擊方向,生成的物體方向也是不一樣的,代碼大致如下:
??? public void CheckAckInteractive(int dir) //參數(shù)為當前的攻擊方向
??? {
??????? float distance = 1.8f;????????? //射線的檢測長度
??????? RaycastHit2D hit2D = new RaycastHit2D();
??????? Vector2 raySize = new Vector2(boxSize.x , boxSize.y);???????? //射線的大小
??????? switch (dir)
??????? {
??????????? case 1:
??????????????? hit2D = Physics2D.BoxCast(transform.position, raySize, 0, Vector2.left, distance, playerLayerMask);
??????????????? break;
??????????? case 2:
??????????????? hit2D = Physics2D.BoxCast(transform.position, raySize, 0, Vector2.right, distance, playerLayerMask);
??????????????? break;
??????????? case 3:
??????????????? hit2D = Physics2D.BoxCast(transform.position, raySize, 0, Vector2.up, distance, playerLayerMask);
??????????????? break;
??????????? case 4:
??????????????? hit2D = Physics2D.BoxCast(transform.position, raySize, 0, Vector2.down, distance, playerLayerMask);
??????????????? break;
??????? }
??????? if (hit2D.collider != null)
??????? {
??????????? if (hit2D.collider.gameObject.CompareTag("Trap"))?? //如果是陷阱就有后坐力
??????????? {
??????????????? var tempObj = Instantiate(attactEffectObj, hit2D.point, Quaternion.identity);//攻擊交互特效
??????????????? switch (dir)//根據(jù)攻擊方向旋轉(zhuǎn)特效物體
??????????????? {
??????????????????? case 1:
??????????????????????? tempObj.transform.rotation = Quaternion.Euler(new Vector3(0, 0, -90));
??????????????????????? break;
??????????????????? case 2:
???????????? ???????????tempObj.transform.rotation = Quaternion.Euler(new Vector3(0, 0, 90));
??????????????????????? break;
??????????????????? case 3:
??????????????????????? tempObj.transform.rotation = Quaternion.Euler(new Vector3(0, 0, 180));
???????????????????? ???break;
??????????????????? case 4://默認方向不需要修改
??????????????????????? break;
??????????????? }
??????????? }
??? }
?
結(jié)語
本系列到了現(xiàn)在項目算是完結(jié)了。雖然我漏掉了音效添加以及一些其余的細節(jié)內(nèi)容,但是完整工程上面其實已經(jīng)添加上去了對應(yīng)的內(nèi)容,需要的童鞋可以下載了解。文章后面還會有一個打包后游戲文件,歡迎下載試玩。(PS:封面沙雕圖來源于百度貼吧@磁力菇1210)
工程下載鏈接:https://pan.baidu.com/share/init?surl=l3zbN8GScoAR3wp3eHp5sQ
提取碼: qd8h
相關(guān)鏈接,很(mai)重(mai)要(mai)
空洞騎士購買鏈接:https://store.steampowered.com/app/367520/Hollow_Knight/
有線下學習游戲開發(fā)打算的童鞋,歡迎訪問:http://www.levelpp.com/
線上課程的傳送門如下:https://study.163.com/course/introduction/1006462005.htm?share=2&shareId=400000000584006
另有專業(yè)開發(fā)交(gao)流(ji)群等待大家強勢插入:869551769