用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

遊資網發表於2019-04-09
用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

前言:

大家好。蟲蟲大冒險(?)新的一期又雙叒叕來了。

本期文章主要講解《空洞騎士中》的地圖搭建相關的內容,並會寫一個簡單的相機指令碼。除此之外,還會涉及到如何製作背景、產生異於玩家移動的動態效果。好了,閒話不多說,直接開始。

地圖模板

工欲善其事,必先利其器。在開始地圖搭建之前,我們先製作好遊戲需要的地圖模板,這樣在後續的地圖搭建環節中可省去大量的時間與精力。

如何搭建地圖模板就不多說了,通過圖片資源對比實際遊戲畫面,然後再組合即可。大約有以下幾種主要的模板:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
多個小圖拼接的地圖模板

值得注意的是,地面與牆壁的柱子形狀的物體的紋理重複使用,是需要在精靈圖片屬性中編輯九宮格,並在SpriteRender-DrawMode中設定為Tiled,並調整引數才能夠有正確的紋理重複的效果。如下:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
設定圖片九宮格相關屬性

這塊技巧在使用Unity製作UI時會頻繁用到,無論什麼遊戲。沒接觸過的童鞋可以留心一下。

由於機關陷阱物體是可以移動的,因而我們還需要寫一個簡單的機關移動指令碼,來控制陷阱的移動。主要邏輯是:先獲取陷阱能夠到達的最上方點與最下方點,然後讓陷阱在其中來回移動。其實現程式碼如下:

  1. public enum TrapMoveDir
  2. {
  3.     None,
  4.     Down,
  5.     Up,
  6. }
  7. public float moveSpeed;//移動速度
  8. public bool isMove=true;//是否進行移動
  9. public Transform startTrans;//開始的點
  10. public Transform endTrans;//結束的點
  11. public Transform trapObj;//陷阱物體
  12. TrapMoveDir moveDir;//移動方向列舉
  13. public void TrapMove()
  14. {
  15.     if (moveDir == TrapMoveDir.Down)
  16.     {
  17.         trapObj.transform.position += transform.up* moveSpeed * Time.deltaTime*-1;//朝下移動
  18.         float distance = Vector3.Distance(trapObj.transform.position, startTrans.position);
  19.         if (distance<0.5f)//如果現在距離最下面的點小於0.5f,重新設定移動方向
  20.         {
  21.             moveDir = TrapMoveDir.Up;
  22.         }
  23.     }
  24.     else if (moveDir == TrapMoveDir.Up)
  25.     {
  26.         trapObj.transform.position += transform.up * moveSpeed * Time.deltaTime;
  27.         float distance = Vector3.Distance(trapObj.transform.position, endTrans.position);
  28.         if (distance < 0.5f)
  29.         {
  30.             moveDir = TrapMoveDir.Down;
  31.         }
  32.     }
  33. }
複製程式碼

地圖分層

為了實現原版遊戲中景深的效果,我們需要正確的利用SpriteRender中提供的層級功能(Sorting Layer或者使用Order in Layer),以製作出想要的效果。其中主要的層級分佈大致如下:(PS:原版遊戲中的層級遠遠超出下面列舉的這幾種,這裡只是簡化版)

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
大致層級圖

優先順序從上到下排列,最上面的的優先順序最高。其中第一層半透明白色遮罩的主要效果,是用於模糊背景物體,產生人物與場景深度不一致的效果。對比如下:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
遮罩效果

第二層的白色半透明遮罩主要用於模糊黑色背景,讓黑色背景跟後面的天空配色不產生衝突。

地圖搭建

在開始搭建地圖之前,推薦自己先畫一個地圖草圖,然後按照草圖進行搭建。搭建的時候可能不會跟草圖一摸一樣,但總是比毫無目標的亂搭一氣好得多。如果你是想做到完全跟原版一樣,那麼這一步你就可以跳過了。類似如下:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

接下來就是按照草圖,選擇合適的地圖模板和對應的圖片搭建地圖了。其中為了實現荊棘地形散亂生長的感覺,沒有製作對應地形的模板,而是根據周圍環境手動調整荊棘圖片的旋轉縮放引數來實現相應的效果。

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

而地圖中窗戶的效果就需要花點心思來實現了。首先需要設定好需要通過窗戶才能夠看見的物體的層級,然後還需要新增比視窗物體層級小的黑色遮罩,來遮擋住其餘不需要被檢視的部分。如下:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

地圖互動

關於玩家與地圖之間的互動,此處就利用碰撞體的Tag屬性,來進行不同的互動效果的觸發。如下圖:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
標籤對應圖

程式碼比較簡單,就是獲取碰撞物體的標籤來執行不同的函式,就不貼出了。

簡易相機

到了這一步,地圖、玩家都準備好了。只需要一個相機遊戲就可以試玩了。

現在我們來寫一個簡單的相機控制指令碼。由於我們是2D遊戲,可以忽略Z軸上的位移來進行相機的移動控制,於是我們的相機的控制原理如下:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
相機移動原理

其實現程式碼如下:

  1.    public Transform player;   //玩家
  2.     Camera playerCamera;        //主相機
  3.     Vector2 boxSize;            //視野範圍
  4.     public bool cameraMove;
  5.     public void FollowPlayer()
  6.     {
  7.         Vector3 targetPos = new Vector3(player.position.x, player.position.y, transform.position.z);
  8.         transform.position = Vector3.Lerp(transform.position, targetPos, 0.08f);//插值進行移動
  9.         float distance = Vector3.Distance(targetPos,transform.position);
  10.         if (distance<0.5f)//距離小於0.5f時 停止移動
  11.         {
  12.             cameraMove = false;
  13.         }
  14.     }

  15.     public void CheckBoundary()
  16.     {
  17.         float leftDistance = 0; //左右距離
  18.         if (player.position.x < transform.position.x) //在左邊
  19.         {
  20.             leftDistance = transform.position.x - player.position.x;
  21.         }
  22.         else
  23.         {
  24.             leftDistance = player.position.x - transform.position.x;
  25.         }
  26.         if (leftDistance > boxSize.x * 0.5f)//如果左右距離大於設定好的矩形寬度的一半
  27.         {
  28.             cameraMove = true;//相機開始移動
  29.         }
  30.         float uDDistance = 0;   //上下距離
  31.         if (player.position.y < transform.position.y)
  32.         {
  33.             uDDistance = transform.position.y - player.position.y;
  34.         }
  35.         else
  36.         {
  37.             uDDistance = player.position.y - transform.position.y;
  38.         }

  39.         if (uDDistance > boxSize.y * 0.5f)
  40.         {
  41.             cameraMove = true;
  42.         }
  43.     }
複製程式碼

背景移動

在現實世界中,人移動時肉眼看遠方,遠處的物體總是移動的比自己慢。而我們就是需要模擬這種特性,來完善我們的景深效果。

實現原理:遊戲一開始獲取玩家的位置並儲存,然後每一幀計算出玩家已經移動的距離,然後使用計算出來的移動位移,來計算出背景此時的座標。程式碼如下:

  1.   public Transform player;
  2.     Vector3 backStartPoint;     //初始背景的位置
  3.     Vector3 playeStartPoint;    //初始玩家的位置
  4.     public void BackMoveFunc()
  5.     {
  6.         float tempX = player.position.x - playeStartPoint.x;
  7.         float tempY = player.position.y - playeStartPoint.y;    //計算X,Y兩軸的歷史位移
  8.         float xVaule = tempX * 0.08f;
  9.         float yVaule = tempY * 0.06f;//計算出背景的X,Y軸位移
  10.         tra
複製程式碼

這裡只讓一層的背景進行移動,如果想要更好的效果,可以多加幾層,使移動的速度不同,這樣的效果將會更加逼真。

演示

敲黑板,專案到了這終於算能夠拿出來瞅瞅了,下面就是現在的演示:(在原文觀看)

結語

新的一期又肝完了。雖然通過這個專案我知道櫻桃遊戲工作室將會比我更肝,但我還是想說:快,馬上,趕緊,quick,哈壓庫,把絲之歌交出來。沒有絲之歌玩我要死了啊。

最後再多說一句。遊戲中還有許多小物體上都是有幀動畫的,包括不限於血條,燈光,陷阱等等。如果你的身體機能滿足下圖:

用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇

可以考慮全都要。(咕咕咕)

工程下載連結
連結:https://pan.baidu.com/s/1DD2_yJh-rulqpNgIDAuZjA提取碼:7gw1
相關連結,很(mai)重(mai)要(mai)
空洞騎士購買連結:https://store.steampowered.com/app/367520/Hollow_Knight/
有線下學習遊戲開發打算的童鞋,歡迎訪問http://levelpp.com/。
線上課程的傳送門如下:簡明易懂的C#入門指南-網易雲課堂study.163.com
另有專業開發交(gao)流(ji)群等待大家強勢插入:869551769

系列文章:
用Unity重現《空洞騎士》的苦痛之路(1):動作篇
用Unity重現《空洞騎士》的苦痛之路(2)——人物控制篇
用Unity重現《空洞騎士》的苦痛之路(3)——地圖篇
用Unity重現《空洞騎士》的苦痛之路(4)——特效篇

作者:繁華如夢
專欄地址:https://zhuanlan.zhihu.com/p/60295559

相關文章