原文:How to Create a Simple Game in Unreal Engine 4
做者:Tommy Tran
譯者:Shuchang Liuhtml
在本篇教程中,你將學習製做一個第一人稱動做遊戲,學習如何隨機生成並躲避障礙物。web
若是你剛開始接觸遊戲,一個經常會收到的建議就是學習製做一款簡單遊戲,由於你能學會製做簡單的遊戲玩法,物件交互。app
本篇教程中,咱們將製做一個第一人稱動做遊戲,涉及如下知識點:dom
最後,咱們將製做出以下圖同樣的小遊戲:編輯器
請注意,教程涉及藍圖和UMG部份內容。若是你須要複習有關內容,請查看藍圖教程和UI教程。ide
注意:本篇教程只是Unreal Engine 4系列教程的其中一篇:svg
下載示例項目並解壓。進入項目文件夾,雙擊InfiniteMatrix.uproject打開項目。函數
注意:若是你看到了項目是由較早的引擎版本建立的提示,這很正常(由於引擎常常更新版本)。你能夠選擇以拷貝副本的形式打開,也能夠直接轉換項目版本打開。oop
按下Play運行遊戲嘗試控制移動。你能夠經過移動鼠標進行垂直,水平移動。學習
首先要作的是讓玩家角色持續向前動起來。
Content Browser打開Blueprints文件夾並雙擊打開BP_Player。
爲了讓玩家角色向前運動起來,咱們須要給玩家位置每幀累加偏移值。
首先,建立變量定義玩家前移的速度。建立名爲ForwardSpeed的Float變量,將默認值調成2000。
接着,在Event Graph找到Event Tick節點,建立以下設置:
經過ForwardSpeed與Delta Seconds相乘,就能得到幀率無關的運動位移。
注意:若是你不熟悉幀率無關的概念,請閱讀藍圖教程。
接着,咱們須要將數值結果應用到角色上,讓其沿指定軸運動。
爲了讓角色移動,建立AddActorWorldOffset節點。將Sweep選中框勾選爲true。
若是咱們直接將Float節點與Delta Location輸入引腳相連,Unreal會將其自動轉換爲Vector。
然而,這樣會致使Vector的x,y,z軸份量都設置成Float節點值。在教程例子中,玩家角色應該只沿着X軸移動。幸運地是,咱們能夠將Vector變量分解成三個Float組件。
確保AddActorWorldOffset節點的Delta Location引腳沒有任何鏈接。右鍵點擊Delta Location引腳,從彈出菜單中選擇Split Struct Pin。
最後,以下圖進行鏈接:
讓咱們回顧下:
點擊Compile並回到主編輯器。角色就會沿着隧道穿行了。
與其手動放置一段段的隧道,咱們接下來會建立藍圖用於自動生成隧道。
Content Browser跳轉到Blueprints文件夾,建立以Actor爲父類的Blueprint Class,命名爲BP_TunnelSpawner並雙擊打開。
因爲遊戲過程會持續不斷的生成隧道,咱們能夠建立一個相應的函數。在My Blueprint面板建立名爲SpawnTunnel的新函數。該函數負責在指定位置建立隧道。
爲了傳遞位置數據,這個函數須要一個輸入參數。它在函數節點以輸入引腳的方式存在。
在函數內部的入口節點,它又以輸出引腳方式存在。
如今讓咱們來建立一個輸入參數。確保界面處於SpawnTunnel函數的圖標。選擇入口節點,而後點擊Details面板Inputs部分的+號。
將輸入參數重命名爲SpawnLocation,並將參數類型改成Vector。
爲了生成隧道,須要添加Spawn Actor From Class節點。點擊Class引腳的下拉框,選擇BP_Tunnel。
爲了設置生成位置,右鍵點擊Spawn Transform引腳,從彈出菜單選擇Split Struct Pin。隨後如圖鏈接Spawn Actor From Class節點與Entry節點:
下面來測試下吧!
切換到Event Graph並找到Event BeginPlay節點。添加SpawnTunnel節點並與Event BeginPlay節點相連。
將SpawnTunnel節點的Spawn Location設置爲(2000, 0, 500)。
如今當遊戲啓動時,隧道會生成在距離玩家角色比較遠的地方。點擊Compile並回到主編輯器。
首先,刪除關卡場景裏的BP_Tunnel。在World Outliner裏左鍵點擊BP_Tunnel,而後按Delete鍵刪除隧道。
接着,在Content Browser裏左鍵拖拽BP_TunnelSpawner至Viewport,這樣就往關卡中添加了對應實例。
如今點擊Play運行遊戲,可以看到玩家角色上方會生成一個隧道。
測試完畢後,再次打開BP_TunnelSpawner。將SpawnTunnel節點的Spawn Location重置爲(0, 0, 0)。
隨後,點擊Compile並返回主編輯器。
教程下一部分,咱們將編寫BP_Tunnel藍圖。
BP_Tunnel藍圖須要幹兩件事。首先它須要檢測什麼時候須要生成一段新隧道。爲了實現這點,咱們須要建立一個觸發區域。一旦觸發,BP_Tunnel負責通知BP_TunnelSpawner生成一段新隧道。這樣就能實現隧道綿延無盡的錯覺。
其次它須要肯定下一段隧道的生成點。BP_TunnelSpawner會根據這個點來生成隧道。
如今先看看怎麼建立觸發區域吧。
打開BP_Tunnel並來到Components面板,添加Box Collision組件,將其命名爲TriggerZone。
此時組件的碰撞區域還很小。留意Details面板的Shape部分設置,將Box Extent屬性改成(32, 500, 500)。
接着,Location屬性設爲(2532, 0, 0),將觸發區域位置擺放到隧道網格末端。這意味着玩家角色觸達隧道末端時就應該生成一段新隧道了。
如今,是時候建立生成點了。
爲了標記生成點位置,咱們可使用Scene組件。Scene組件很是適合用於標記位置,由於該組件沒有外觀顯示,只有一個Transform。同時該組件在Viewport又是可視的,方便咱們知道生成點在哪。
沒有選中任何東西的前提下,在Components面板添加Scene組件,並命名爲SpawnPoint。
隧道網格沿X軸總共2500單位長,因此生成點應該就在這,在Details面板設置Location參數爲(2500, 0, 0)。
接下來須要建立一個函數,負責在生成點生成隧道。
點擊Compile並切換到BP_TunnelSpawner。
新的BP_Tunnel永遠應該在最遠隧道的生成點生成。這樣看起來,隧道就是無窮盡的。
因爲最遠隧道一定是最新生成的隧道,因此咱們不難得到其引用。
打開SpawnTunnel圖表,在Spawn Actor From Class節點的Return Value引腳右鍵點擊,從彈出菜單中選擇Promote to Variable並命名爲NewestTunnel。
如今,咱們就得到了最遠隧道的引用了。
接着,建立新函數並命名爲SpawnTunnelAtSpawnPoint。建立以下圖表:
這樣設置就能夠得到SpawnPoint組件的位置,並在該點生成一段新隧道。
爲了讓BP_Tunnel能通知調用到BP_TunnelSpawner,前者須要有後者的引用。不然,BP_TunnelSpawner就不知道什麼時候生成隧道了。
點擊Compile並關閉SpawnTunnelAtSpawnPoint圖表,隨後打開BP_Tunnel。
添加新變量,命名爲TunnelSpawner,將Variable Type類型設置爲BP_TunnelSpawner\Object Reference。
點擊Compile並切換回BP_TunnelSpawner。
打開SpawnTunnel圖表添加對應節點:
如今,每一個隧道都能得到BP_TunnelSpawner的引用。
接着,咱們要讓BP_TunnelSpawner能在玩家角色進入觸發區域時生成新隧道。
點擊Compile並切回到BP_Tunnel。
在Components面板右鍵點擊,在彈出菜單中選擇Add Event\Add OnComponentBeginOverlap。Event Graph會新增下面節點:
這個節點會在Actor觸碰觸發區域時執行。
首先,咱們要確認觸碰觸發區域的Actor是玩家角色。
左鍵拖拽Other Actor引腳至空白處,從彈出菜單中選擇Cast to BP_Player節點。
注意:因爲新隧道會在另外一段隧道的末端生成,它會觸發執行隧道的TriggerZone節點,Cast to BP_Player節點能攔截其餘Actor執行後續邏輯。
接着,在Cast to BP_Player節點後面添加以下節點:
讓咱們再回顧以上步驟:
點擊Compile,回到主編輯器並點擊Play。一旦觸達隧道末端,就會又有一段隧道生成。
至此,雖然遊戲一直在生成隧道,看起來並不像穿行在無盡的隧道。咱們能夠經過在屏幕上多顯示幾條隧道來優化畫面表現。後面再配合上障礙點的顯示,玩家就不會留意到隧道的忽然生成了。
首先,咱們要建立函數用於生成必定數量的隧道。
打開BP_TunnelSpawner建立名爲SpawnInitialTunnels的新函數。
爲了生成必定數量的隧道,咱們可使用ForLoop節點。該節點會執行屢次鏈接的節點。添加ForLoop節點並與入口節點相連。
爲了使得ForLoop節點執行n次,咱們須要將Last Index設置成n-1。
在這篇教程裏,咱們須要生成3段隧道,爲了循環執行3次,將Last Index設置成2。
注意:若是不顯式設置First Index或Last Index字段,默認爲0。
玩家應該在遊戲開始時就處於隧道中,因此咱們能夠將第一段隧道生成在玩家位置。
爲了判斷第一段隧道是否已生成,咱們能夠檢查NewestTunnel字段是否有值。若是沒有值則說明第一段隧道還未生成,由於NewestTunnel字段是在遊戲生成第一段隧道後設值的。
爲了進行檢查,在ForLoop節點後添加IsValid節點(帶有問號圖標)。
接着,獲取NewestTunnel引用鏈接IsValid節點的Input Object引腳。
若是NewestTunnel沒有值,執行Is Not Valid引腳,反之執行另外一個引腳。
在IsValid節點的Is Not Valid引腳分支添加以下節點:
這樣就能在玩家位置生成一段隧道。
好了,接下來讓咱們來生成其餘隧道。
添加SpawnTunnelAtSpawnPoint節點並與IsValid節點的Is Valid引腳鏈接。
下圖就是最終圖表:
小結:
接着,在Event Graph中刪除SpawnTunnel節點,並在Event BeginPlay節點後添加SpawnInitialTunnels節點。
如今再運行遊戲,就會生成了3段隧道。
點擊Compile,回到主編輯器點擊Play。隧道看起來長多了!
這個遊戲目前爲止尚未遊戲難度,讓咱們來加上一些障礙點。
這些是咱們建立障礙點會用上網格:
在Components面板雙擊打開BP_Tunnel。添加Static Mesh組件,命名爲WallMesh。
在Details面板將它的Static Mesh屬性改成SM_Hole_01。
再將Location屬性改成(2470, 0, 0)。這樣網格就會處於隧道末端位置。
爲了讓遊戲更有趣些,最好讓這面障礙牆轉動起來。添加Float變量,命名爲RotateSpeed,設置默認值爲30。
切換到Event Graph找到Event Tick。進行以下設置:
這樣WallMesh每幀都會轉動一點點。
點擊Compile並返回主編輯器。按下Play看看轉動的障礙牆吧。
接着讓咱們再來添加一些隨機性吧。
在此咱們不須要給每種不一樣樣式的障礙都建立一個藍圖,咱們只要隨機選擇WallMesh便可。
打開BP_Tunnel並建立新函數RandomizeWall。隨後,以下圖設置圖表:
顧名思義,Set Static Mesh節點會將WallMesh設置爲指定的網格。
想要建立一個網格列表,咱們可使用Select節點。
左鍵拖拽New Mesh引腳至空白處,從彈出菜單中選擇Select節點。
Select節點容許你設置一個選項列表。Index節點決定Select節點輸出哪一個列表選項。
既然有4個可用牆面網格,咱們須要再建立2個Option引腳。經過右鍵點擊Select節點,從彈出菜單中選擇Add Option Pin。
接着,以下設置每一個選項:
如今,再隨機選中一個選項。
咱們可使用Random Integer in Range節點來獲取一個隨機數字,該節點會返回>=Min且<=Max的數值。
添加Random Integer in Range節點並與Select節點的Index引腳相連。
將Max值設爲3。這樣就會隨機返回如下4個數字中的一個:0,1,2,3。
爲了增長一些隨機性,咱們再給WallMesh添加一個隨機旋轉值。在Set Static Mesh節點後添加以下圖表:
這樣WallMesh就會有一個0~360度的旋轉偏移值。
下圖是最終的圖表:
小結:
點擊Compile並關閉RandomizeWall圖表。
切換到BP_TunnelSpawner並打開SpawnTunnel圖表。添加下圖的高亮節點:
如今,只要建立隧道,都會跟着隨機生成障礙牆網格。
關閉SpawnTunnel圖表並點擊Compile。返回主編輯器並按下Play體驗不一樣的障礙牆!
若是你撞上了牆,應該會立刻停下來。若是你控制移動並穿過了牆上的洞,就能夠繼續前行。
咱們下一步要作的是讓玩家角色在撞上牆後中止移動。
要控制玩家角色能不能前行,咱們可使用Boolean變量。該變量只有兩種狀態:true和false。
打開BP_Player並建立新Boolean變量,命名爲IsDead。
接着,找到Event Tick節點並建立Branch節點。
隨後,獲取IsDead引用並鏈接Branch節點的Condition引腳。
鏈接Event Tick節點與Branch節點。隨後,鏈接Branch節點的False引腳與AddActorWorldOffset節點。
如今,只要IsDead設置爲true,玩家角色就會中止移動。
接着,咱們要在玩家撞到牆時設置IsDead變量。
點擊Compile並切換到BP_Tunnel。在Components面板右鍵點擊WallMesh,在彈出菜單中選擇Add Event\Add OnComponentHit。Event Graph就會新增以下節點:
只要Actor跟WallMesh觸碰,節點就會執行。
首先,咱們須要檢查碰撞Actor是否爲玩家。
左鍵拖拽Other Actor引腳至空白處,從彈出菜單中選擇Cast to BP_Player。
接着,左鍵拖拽Cast to BP_Player節點的BP_Player引腳至空白處,從彈出菜單中選擇Set Is Dead節點。
將IsDead的勾選框勾選爲true。
點擊Compile並回到主編輯器。點擊Play嘗試在遊戲撞上牆。你會發現你還能夠上下移動,但已經再也不繼續前行了。
下一部分教程,咱們將要在玩家撞上牆時顯示重玩按鈕。
咱們要顯示的控件叫WBP_Restart。你能夠在UI文件夾找到它。控件看起來是這個樣子的:
爲了控制控件的顯隱,首先要得到它的引用。打開BP_Player並建立變量RestartWidget,將Variable Type改成WBP_Restart\Object Reference。
接着,在Event Graph找到Event BeginPlay節點。
新增Create Widget節點並設置Class爲WBP_Restart。
隨後,添加Set Restart Widget節點並以下圖鏈接:
如今,當玩家生成時,會同時生成WBP_Restart實例。下一步是建立函數來顯示它。
建立名爲DisplayRestart的新函數,而後以下圖設置其圖表:
小結:
要顯示重玩按鈕,咱們所要作的事就是在玩家撞牆後,調用DisplayRestart函數。
關閉DisplayRestart圖表並點擊Compile。
切換到BP_Tunnel並找到On Component Hit (WallMesh)節點。
在節點鏈的末端添加DisplayRestart節點。
點擊Compile並關閉BP_Tunnel。回到主編輯器並點擊Play。若是你撞上了牆,就會顯示重玩按鈕。
如今還剩最後一步工做,在玩家點擊按鈕後重置遊戲。
重置遊戲須要作兩件事:
首先咱們先來重置玩家。
打開BP_Player並建立新函數RestartGame,建立以下圖表:
小結:
而後,咱們還須要從新生成隧道。
點擊Compile並關閉BP_Player。
打開BP_TunnelSpawner並跳轉到SpawnInitialTunnels圖表。
首先,在生成新隧道前,要先把此前生成的隧道所有移除掉。
在入口節點後面添加Sequence節點。將Then 1引腳與ForLoop節點相連。
注意:Sequence節點用於序列執行它的輸出引腳。善用Sequence節點有利於圖表的組織,特別是一味濫用節點鏈的狀況下,圖表會變得很是長。
接着,建立以下節點:
這樣就能把此前生成的隧道所有移除掉。
最後,將Sequence節點的Then 0引腳與Get All Actors of Class節點相連。這樣就能確保在生成新隧道前,移除已有隧道。
看看最終的圖表:
還剩最後一件事了,處理按鈕點擊。
點擊Compile並關閉BP_TunnelSpawner。
打開Content Browser的UI文件夾,雙擊打開WBP_Restart。
選中RestartButton並打開Details面板,點擊Events下的OnClicked右側按鈕。
Unreal會建立On Clicked (RestartButton)節點。這個節點會在玩家點擊RestartButton時觸發執行。
以下圖設置函數圖表:
小結:
注意:你可能奇怪咱們要用Get All Actors Of Class節點,而不是直接獲取BP_TunnelSpawner引用。主要緣由是BP_Tunnel與WBP_Restart並無任何引用關係。對於這樣的一個簡單遊戲,用這種方式得到引用比較簡單粗暴點。
點擊Compile並關閉藍圖編輯器。按下Play測試下剛實現的重玩按鈕吧!
你能夠在這裏下載完整項目。
如今你已經有了一個簡單可玩的遊戲,試着在此基礎進一步完善豐富遊戲。好比按玩家穿越了多少障礙點來進行計分。
你也能夠嘗試製做像Pong或俄羅斯方塊這樣的經典遊戲。這些遊戲機制都很簡單,但實現起來都有必定難度。
若是你還想繼續學習引擎其餘內容,點擊下篇教程,講解如何在遊戲中利用藍圖實現角色動畫。