【UE4教程文檔翻譯】First Person Shooter C++ Tutoria(第一人稱射擊C++教程)



1、本文爲題主在學習中翻譯,同時在UE4.10.2 版本上嘗試運行,翻譯過程中遇到翻譯不出會暫時留白,翻譯有誤請指出,謝謝!
2、本文在翻譯過程中遇到題主不懂的地方可能會添加題主的知識擴展鏈接。

3、轉載請註明出處。謝謝!

4、原文地址:點擊打開鏈接
---------------------------------------------------------------------------------------------

感謝:

在此對題主好友Erin表示感謝。感謝Erin在這一系類中指出並校正有誤的地方。

-------------------------------------------------------------------------------------------

First Person Shooter C++ Tutorial

第一人稱射擊C++教程


Warning:
 This tutorial may be outdated for newer versions of Unreal Engine.

警告:該教程可能不適用新版本虛幻引擎

PS:以下目錄默認鏈接爲官網連接,翻譯完成後將更改爲CSDN上翻譯後的博客鏈接。不便之處,還請原諒。謝謝!
PS:已更改爲翻譯後CSDN博客鏈接。
PS:所有章節已整合在一起。
PS:該教程適合入門,涉及到了C++、藍圖、碰撞、動畫等知識,按照該教程,可初步熟悉UE4引擎。

Overview —— 概述

Over the course of this tutorial, you will transform a blank project template into the beginnings of a first-person shooter, with a character that moves and strafes, camera control, and projectiles you can fire at the environment. Using C++, you will create a GameMode, Character and HUD.

本教程中,你會從一個空白的項目模板入手,從而開始第一人稱射擊,在該環境中包括了角色的移動和掃射、攝像機控制,以及你可以開火的子彈。使用C++,你可以創建GameMode、角色和HUD。

---------------------------------------------------------------------------------------------

Starting a New Project —— 新建項目

We will create a blank project as the starting point for our FPS game, using Unreal Engine 4's Project Browser.

我們將使用UE4的項目瀏覽器,新建空項目作爲我們FPS遊戲的初始點。

1. Open Unreal Editor.

打來虛幻編輯器。

2. In the Project Browser, click on the New Project tab.

在項目瀏覽器中點擊NewProject標籤頁。

3. Select the Blank project.

選擇Blank project。

4. Name the project FPSProject and uncheck the Copy starter content into new project? checkbox. (Uncheck "Include starter content checkbox" for UE 4.2.0)

項目名命名爲FPSProject,不勾選Copy starter content into new project?選項框。(PS:UE4.10選擇"without starter content")

NewFPSProject.png


Note that some of the code samples provided in this tutorial will require alteration if the project's name is different, and we will make note of that at the appropriate step.

要的注意的是,如果項目名不一樣的話,則需要改變本教程提供的一些代碼樣本,我們會在相應步驟進行註釋。

5. Click on Create.

點擊Create。

6. Your project is now open in Unreal Editor. You can play in the starting level by clicking on the Play In button in the Level Editor Toolbar. The WASD keys will allow you to fly around within the level, and the mouse will aim your camera. Press Escape when you are ready to exit Play in Editor (PIE) mode.

現在,你的工程已經在虛幻編輯器打開。你可以點擊關卡編輯工具欄上的Play按鍵從而在開始關卡中玩耍了。其中WASD按鍵可以讓你在關卡中飛行,鼠標可以移動你的相機視角。按下Escape即可退出PIE模式。

New level in editor.png


7. Create a Maps folder within the Content folder.

在Content文件夾下新建Maps文件夾。

8. In the File menu, select Save as... to save your map as FPSMap within the Maps folder.

File 菜單中選擇Save as... 將你的map命名爲FPSMap保存到Maps文件夾下

9. In the Edit menu, click on Project Settings.

Edit 菜單中,選擇Project Settings

10. Under the Game heading on the left side of the Project Settings tab, click on Maps & Modes.

Project Settings 標籤左側Game標題下,點擊。Maps & Modes

11. Using the dropdown, select FPSMap as the Editor Startup Map. Now, whenever you re-open your project in the editor, you will automatically load this map.

使用下拉,選擇FPSMap作爲Editor Startup Map。現在,無論你何時在編輯器中重啓你的項目,都會自動加載該map。

Editor startup map.png


12. Close the Project Settings menu.

關閉Project Settings菜單

---------------------------------------------

Creating a GameMode ——創建GameMode

傳送門:GameMode官方文檔說明

Let's create a GameMode. A GameMode contains the definition of the game itself, such as game rules, win conditions, etc. It also sets the default classes to use for some basic gameplay framework types, including Pawn, PlayerController, and HUD. Before we set up our FPS character, we need to create the GameMode that will reference it.

創建GameMode。GameMode包含了遊戲本身的定義,如遊戲規則,過關條件等等。它還爲遊戲架構類型設置了默認類,包括Pawn, PlayerController, and HUD。在我們創建我們的FPS角色之前,我們需要創建一個與之相關的GameMode。

First, we are going to use the C++ Class Wizard to add a new class to our project.

首先,我們將使用C++類嚮導爲項目添加一個類。

1.In the File menu, select Add Code to Project.

在File菜單中,選擇Add Code to Project。

2. Scroll down and select GameMode as the parent class. Click Next.

向下滾動,選擇GameMode作爲父類,點擊Next.

Choose gamemode.png


3. Name the new class FPSGameMode, then click Create.

類名命名爲FPSGameMode,點擊Create。

4. Click on Yes to open the class in Visual Studio or XCode for editing.

點擊Yes在VS或XCode中打開進行編輯。

Since this is the first code we've added to the project, the wizard will also create the initial files needed to compile and run our project.

由於這是我們添加到項目中的第一個代碼,該向導還將創建項目編譯和運行所需的初始文件。

We will add a log message to the FPSGameMode, so that when we start playing in our level, we can see that we are actually using our new GameMode. We will add code to FPSGameMode's constructor, so that it will run when gameplay begins.

我們將爲FPSGameMode添加一個日誌信息,這樣當我們開始在我們的關卡中運行的時候,我們可以看到,我們實際上是在使用新的GameMode。我們將代碼添加到FPSGameMode構造函數中,這樣它會遊戲開始時運行。

1. Your code IDE will open.

打開你的代碼編輯器。

2. In the Solution Explorer, expand FPSProject > Source > FPSProject.

在Solution Explorer中,按FPSProject > Source > FPSProject擴展開。

3. Here, you will see the header file for your new FPSGameMode class, FPSGameMode.h. Double-click it to open it for editing.

在這裏,你會看到你新建類FPSGameMode的頭文件——FPSGameMode.h。雙擊打開。

4. Find the class declaration, which looks like:

找到類聲明,如下:

UCLASS()
class FPSPROJECT_API AFPSGameMode : public AGameMode
{
GENERATED_BODY()
};

5. Under GENERATED_BODY(), add the following lines then save the file.

在GENERATED_BODY()下,添加下面代碼後保存

virtual void StartPlay() override; // Note that engine version 4.3 changed this method's name to StartPlay(), because of this engine versions before 4.3, or older tutorials, use BeginPlay()

This function declaration will allow you to override the StartPlay() function inherited from the `AActor` class, so that you can print a message to the screen when gameplay begins.

該函數聲明將重寫繼承自 'AActor' 的StartPlay()函數,因此你可以在遊戲開始時在屏幕上輸出消息。

Note: 4.6 needs below line to be included (before or after StartPlay(). This is the definition of constructor whose signature is also different from older versions.

注意:4.6需要加入以下代碼(在StartPlay()之前之後,這是與舊版本簽名不同的構造函數的定義)


AFPSGameMode(const FObjectInitializer& ObjectInitializer);

6. Open FPSGameMode.cpp. It is located in FPSProject > Source > FPSProject as well.

打開FPSGameMode.cpp,它同樣位於FPSProject > Source > FPSProject。

If your project has a different name, your code will be located in [ProjectName] > Source > [ModuleName]. The module name is the same as your project name because you used the C++ Class Wizard.
如果你有不同的項目名,你的代碼將位於 [ProjectName] > Source > [ModuleName].模塊名和你的項目名一致,因爲你是用的C++類嚮導。

First, at the top of the file, add the following line under the other #include lines:

首先,在文件的開頭,包含如下頭文件


#include "Engine.h" //for version 4.4+
// Note that this may no longer be necessary as this file will likely already include [ProjectName].h, which, by default, will include "Engine.h" itself

7. Find FPSGameMode's constructor. It looks like:

找到FPSGameMode的構造函數,如下:

Note: In 4.6 this is no longer correct as the procedure for constructors has changed, you will not find this code. You will need to write the following line of code in if it is not present For users of previous versions, FPostConstructInitializeProperties is replaced with FObjectInitializer and variable name PCIP with ObjectInitializer (though variable name can be anything, its recommended to change as a good practice)

注意:在4.6這不再正確,因爲構造函數的程序已改變。你不會找到這條代碼。如果它不存在,你需要編寫以下代碼。對於以前版本的用戶,FPostConstructInitializeProperties已替換爲FObjectInitializer,且變量名由PCIP替換爲ObjectInitializer(雖然變量名可以是任何東西,它推薦的做法更爲妥當)

AFPSGameMode::AFPSGameMode(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
 
}
The prefixed name of FPSGameMode is AFPSGameMode, because it derives from a class which eventually derives from the Actor class.
FPSGameMode 的前綴名爲 AFPSGameMode,因爲他的父類繼承與Actor類

8. After the constructor, add the following lines, then save the file.

在構造函數後面,添加以下代碼並保存。

// Note that engine version 4.3 changed the method's name to StartPlay(), because of this engine versions before 4.3, or older tutorials, use BeginPlay()
void AFPSGameMode::StartPlay() 
{
      Super::StartPlay();
 
      StartMatch();
 
      if (GEngine)
      {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("HELLO WORLD"));
      }
}

This function definition will print "HELLO WORLD" to the screen in yellow text when gameplay begins.

在遊戲開始時,該函數將在屏幕上打印出黃色文本"HELLO WORLD"。

We will now compile our project, so that we can see our code changes reflected in the game. If you are using Unreal 4.6 or below, you need to close the editor, compile, and then reopen the project in the editor to reload the game module.現在編譯我們的項目,這樣就可以在遊戲中我們

代碼實現。如果你使用4.6或更低版本,你需要關掉編輯器,編譯,然後在編輯器重啓項目或則重新加入遊戲模塊。(PS:入門4.10,表示不需要……^_^)。

1. If you are using Visual Studio, make sure that you have set up Visual Studio for compiling with Unreal Engine.

如果你使用VS,確保你設置了VS可爲UE編譯。

2. Close Unreal Editor. (Not required in 4.7)

關掉虛幻編輯器(4.7不需要,PS:4.10同樣不要)。

3. Compile.

編譯。

4. After the build finishes, open Unreal Editor, and then open FPSProject.

完成build,打開FPSProject項目。

We need to set the project to use FPSGameMode as the default GameMode.

我們需要在項目中將FPSGameMode設置爲默認的GameMode.

1. In the Edit menu, click on Project Settings.

Edit -> Project Settings.

2. Under the Game heading on the left side of the Project Settings tab, click on Maps & Modes.

Project Settings 標籤左側Game標題下,點擊。Maps & Modes

3. Select FPSGameMode in the Default GameMode dropdown.

Default  GameMode下拉列表中選擇FPSGameMode

FPSGameMode.png


4. Close the Project Settings menu.

關閉Project Settings 菜單。

5. Click on the Play In button in the Level Editor Toolbar. "HELLO WORLD" should be displayed in the upper left corner of the viewport.

點擊Play.Viewport左上角出現"HELLO WORLD"。

HelloWorldGameMode.png


You can also look in the Scene Outliner while your game is running to see FPSGameMode listed.

遊戲運行時,在Scene Outliner 中可以看到FPSGameMode .

6. Press Escape to exit Play in Editor (PIE) mode.

按下Escape退出PIE模式

--------------------------------------------------------------------------------------------------------------

PS:按照以上教程,題主在UE4.10.2版本中實現上述功能。

附代碼.h

  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #pragma once  
  4.   
  5. #include "GameFramework/GameMode.h"  
  6. #include "MyFPSProjectGameMode.generated.h"  
  7.   
  8. /** 
  9.  *  
  10.  */  
  11. UCLASS()  
  12. class MYFPSPROJECT_API AMyFPSProjectGameMode : public AGameMode  
  13. {  
  14.     GENERATED_BODY()  
  15.       
  16. public:  
  17.     virtual void StartPlay() override;  
  18.     AMyFPSProjectGameMode(const FObjectInitializer& ObjectInitializer);  
  19. };  
.cpp
  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #include "MyFPSProject.h"  
  4. #include "MyFPSProjectGameMode.h"  
  5.   
  6. AMyFPSProjectGameMode::AMyFPSProjectGameMode(const FObjectInitializer& ObjectInitializer):Super(ObjectInitializer)  
  7. {  
  8.       
  9. }  
  10.   
  11. void AMyFPSProjectGameMode::StartPlay()  
  12. {  
  13.     Super::StartPlay();  
  14.   
  15.     StartMatch();  
  16.   
  17.     if (GEngine)  
  18.     {  
  19.         GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("HELLO WORLD"));  
  20.     }  
  21. }  

------------------------------------------------------------------------------------------------------------

Making a Character —— 創建角色

The engine has a built-in class called DefaultPawn which is a Pawn with some simple disembodied flying movement. We want to have a human-like avatar walking on the ground, so let's create our own Pawn to control. The engine includes a class for this called Character, which derives from Pawn but has built in functionality for bipedal movement like walking, running, and jumping. We will use Character as the base class for our FPS Pawn.

引擎有一個內置的DefaultPawn類,它是一個可簡單飛行運動的Pawn。我們希望有類似人類行走的avatar,那麼就創建一個可控制的Pawn把。引擎含有一個叫做Character的類,它繼承自Pawn,但是具有類似行走、跳躍的雙足運動功能,我們將使用Character作爲FPS Pawn的基類

Again, we will use the C++ Class Wizard to add this new class to our project. It is possible to manually add the *.h and *.cpp files to your Visual Studio solution to add new classes, but the C++ Class Wizard fills in header and source templates which set up the Unreal-specific macros for us, which simplifies the process.

接着,我們使用C++類嚮導新建類到我們的項目中。可以手動添加Visual Studio

1. In the File menu, select Add Code to Project.

在File菜單中,選擇 Add Code to Project.

2. Scroll down and select Character as the parent class. Click Next.

下滑選擇Character 作爲基類,點擊Next

3. Name the new class FPSCharacter, then click Create.

新類命名爲FPSCharacter,點擊Create

4. Click on Yes to open the class in Visual Studio for editing.

點擊Yes並在VS中打開類。

5. Visual Studio will prompt you asking to reload the project, since the C++ Class Wizard modified it. Select Reload.

Visual Studio會提示你是否重新加載項目,由於C ++類嚮導修改了它,因此選擇刷新。

Fps reload project.png


First, we will edit our GameMode, so that FPSCharacter is the default Pawn used when starting gameplay.

首先,我們編輯GameMode,從而開始遊戲時FPSCharacter作爲被使用的默認Pawn.

1. First go to FPSGameMode.h. Below GENERATED_BODY() we will now add a constructor for the class, the following will be what our class looks like now (Engine Version 4.6).

首先前往GENERATED_BODY() 下爲類添加構造函數,以下就是我們的程序(UE4.6)

UCLASS()
class FPSPROJECT_API AFPSGameMode : public AGameMode
{
	GENERATED_BODY()
 
	AFPSGameMode(const FObjectInitializer& ObjectInitializer);  // Our added constructor
 
	virtual void StartPlay() override;
};

2. Return to FPSGameMode.cpp. First, at the top of the file, add the following line under the other #include lines:

返回FPSGameMode.cpp。首先,在文件頂部其他的#include下添加下面的的頭文件

#include "FPSCharacter.h"

3. Then, we will find the constructor we previously added in FPSGameMode.cpp:

接着,找到我們之前在FPSGameMode.cpp添加的構造函數。


AFPSGameMode::AFPSGameMode(const class FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

4. And following that we add the following line to the constructor:

在構造函數添加下面的代碼

DefaultPawnClass = AFPSCharacter::StaticClass();

This tells the GameMode which type of Pawn to spawn for the player when starting the game.

它會告訴GameMode在遊戲啓動時那種類型的Pawn會生成給玩家(PS:spawn for不知道怎麼翻譯好

The constructor for FPSGameMode will now look like:

現在FPSGameMode的構造函數是這樣的:

AFPSGameMode::AFPSGameMode(const class FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	DefaultPawnClass = AFPSCharacter::StaticClass();
}

Now, save the files.

現在,保存文件。

Let's also add an on-screen message to FPSCharacter, so we can be sure our new class is being used properly.

讓我們也給FPSCharacter添加一個屏幕消息,以確保我麼的新類被正確使用。

1. Open FPSCharacter.h. It is located in FPSProject > Source > FPSProject.

打開FPSCharacter.h,它位於 FPSProject > Source > FPSProject.

If your project has a different name, your code will be located in [ProjectName] > Source > [ModuleName]. The module name is the same as your project name because you used the C++ Class Wizard.

如果你的項目名和教程不同,你的代碼會位於[項目名] > Source > [模塊名],項目名與模塊名一致。

2. Find the class declaration, which looks like:

找到類聲明,類似這樣:

class FPSPROJECT_API AFPSCharacter : public ACharacter
{
	GENERATED_BODY()
 
};

3. Under GENERATED_BODY(), add the following line, then save the file.

GENERATED_BODY()下,添加以下代碼

virtual void BeginPlay() override;

This function declaration will allow you to override the BeginPlay() function inherited from the AActor class, so that you can print a message to the screen when gameplay begins.

這個函數聲明允許你重寫繼承自AActor的BeginPlay()函數,從而在啓動遊戲時屏幕輸出消息。

4. Now open FPSCharacter.cpp and add the following lines, then save the file.

打開FPSCharacter.cpp,添加下面代碼並保存。

void AFPSCharacter::BeginPlay()
{
      Super::BeginPlay();
 
      if (GEngine)
      {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("We are using FPSCharacter!"));
      }
}

This function definition will print "We are using FPSCharacter!" to the screen in blue text when gameplay begins.

遊戲啓動時,該函數會在屏幕顯示藍色文本"We are using FPSCharacter!"

We will again close the editor and compile our project, so that we can see our code changes reflected in the game. (Note that you should be able to hot-reload if you are using the latest engine version, which means you can compile without closing the Unreal Editor.)

關掉編輯器編譯項目,可以在遊戲中反映出代碼的改變。

1. Close Unreal Editor.

關掉虛幻編輯器

2. Compile.

編譯(PS:4.10版本可直接編譯,因爲它具有熱更新功能)

3. After the build finishes, open Unreal Editor, and then open FPSProject.

編譯完成後,打開虛幻編輯器,打開FPSProject.

4. Click on the Play In button in the Level Editor Toolbar. Your new Character does not have any movement controls yet, so you will not be able to move around in the level. So, if you are stuck and unable to move, you are using the FPSCharacter as your Pawn correctly! Your log message should also be displayed on the screen.

點擊Play.你的Character還沒有運動控制,所以你還不能在關卡中移動。所以如果你動不了,便表示正確使用了作爲Pawn的FPSCharacter.你的日誌消息也會顯示在屏幕上。(PS:以後類似點擊關卡編輯工具欄上的Play按鍵就直接說點擊Play了,這幾個章節用下來,基本上能找到哪裏是哪裏,就不再贅述了。)

Logmessage character.png


You can also look in the Scene Outliner while your game is running to see FPSCharacter listed.

5. Press Escape to exit Play in Editor (PIE) mode.

Esc退出。

---------------------------------------------------------

4.10上運行,源碼如下(PS:題主GameMode類命名爲MyFPSProjectGameMode了

MyFPSProjectGameMode.h

  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #pragma once  
  4.   
  5. #include "GameFramework/GameMode.h"  
  6. #include "MyFPSProjectGameMode.generated.h"  
  7.   
  8. /** 
  9.  *  
  10.  */  
  11. UCLASS()  
  12. class MYFPSPROJECT_API AMyFPSProjectGameMode : public AGameMode  
  13. {  
  14.     GENERATED_BODY()  
  15.       
  16. public:  
  17.     virtual void StartPlay() override;  
  18.     AMyFPSProjectGameMode(const FObjectInitializer& ObjectInitializer);  
  19. };  
MyFPSProjectGameMode.cpp
  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #include "MyFPSProject.h"  
  4. #include "MyFPSProjectGameMode.h"  
  5. #include "FPSCharacter.h"  
  6.   
  7. AMyFPSProjectGameMode::AMyFPSProjectGameMode(const FObjectInitializer& ObjectInitializer):Super(ObjectInitializer)  
  8. {  
  9.     DefaultPawnClass = AFPSCharacter::StaticClass();  
  10. }  
  11.   
  12. void AMyFPSProjectGameMode::StartPlay()  
  13. {  
  14.     Super::StartPlay();  
  15.   
  16.     StartMatch();  
  17.   
  18.     if (GEngine)  
  19.     {  
  20.         GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("HELLO WORLD"));  
  21.     }  
  22. }  
FPSCharacter.h
  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #pragma once  
  4.   
  5. #include "GameFramework/Character.h"  
  6. #include "FPSCharacter.generated.h"  
  7.   
  8. UCLASS()  
  9. class MYFPSPROJECT_API AFPSCharacter : public ACharacter  
  10. {  
  11.     GENERATED_BODY()  
  12.   
  13. public:  
  14.     // Sets default values for this character's properties  
  15.     AFPSCharacter();  
  16.   
  17.     // Called when the game starts or when spawned  
  18.     virtual void BeginPlay() override;  
  19.       
  20.     // Called every frame  
  21.     virtual void Tick( float DeltaSeconds ) override;  
  22.   
  23.     // Called to bind functionality to input  
  24.     virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;  
  25.   
  26.       
  27.       
  28. };  
FPSCharacter.cpp
  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #include "MyFPSProject.h"  
  4. #include "FPSCharacter.h"  
  5.   
  6.   
  7. // Sets default values  
  8. AFPSCharacter::AFPSCharacter()  
  9. {  
  10.     // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.  
  11.     PrimaryActorTick.bCanEverTick = true;  
  12.   
  13. }  
  14.   
  15. // Called when the game starts or when spawned  
  16. void AFPSCharacter::BeginPlay()  
  17. {  
  18.     Super::BeginPlay();  
  19.     if (GEngine)  
  20.     {  
  21.         GEngine->AddOnScreenDebugMessage(-1, 5.f,FColor::Blue, TEXT("We are using FPSCharater"));  
  22.     }  
  23.       
  24. }  
  25.   
  26. // Called every frame  
  27. void AFPSCharacter::Tick( float DeltaTime )  
  28. {  
  29.     Super::Tick( DeltaTime );  
  30.   
  31. }  
  32.   
  33. // Called to bind functionality to input  
  34. void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)  
  35. {  
  36.     Super::SetupPlayerInputComponent(InputComponent);  
  37.   
  38. }  

--------------------------------------------------------------------------------------------------------------

WASD Movement —— WASD移動

Let's get our new Character moving around.

讓我們的新角色遛起來。

We will go through specifics of input processing in the next several steps, but you may also find the general overview of input framework useful to refer to.

我們將在接下來的幾個步驟瞭解input(輸入)細節,但你也會發現input框架的概述值得去參考(PS:這裏可能是說參考官方說明文檔)。

The input controls for walking around in the world, such as WASD or arrow keys, are usually set up with axis mappings.

如WASD或者方向鍵的行動輸入控制,通常設置了軸映射。

Axis Mappings —— 軸映射

Map keyboard, controller, or mouse inputs to a "friendly name" that will later be bound to continuous game behavior, such as movement. The inputs mapped in AxisMappings are continuously polled, even if they are just reporting that their input value is currently zero. This allows for smooth transitions in movement or other game behavior, rather than the discrete game events triggered by inputs in ActionMappings. Hardware axes, such as controller joysticks, provide degrees of input, rather than discrete 1 (pressed) or 0 (not pressed) input. That is, they can be moved to a small degree or a large degree, and your character's movement can vary accordingly. While these input methods are ideal for providing scalable amounts of movement input, AxisMappings can also map common movement keys, like WASD or Up, Down, Left, Right, to continuously-polled game behavior.

映射鍵盤、控制器或者輸入 到一個“友好名字”將會在之後綁定到連續的遊戲行爲,比如行動。軸映射中的的輸入映射不斷輪詢,即使他的輸入值近乎爲0。它允許在運動或其他遊戲行爲中平滑過渡,而不是由ActionMappings中的輸入觸發的離散遊戲事件。如搖桿控制器提供了輸入量而不是離散的1(按下)或0(擡起)輸入。也就是說,它們可大可小,而你的角色運動速度也會隨之而變。雖然這些輸入方法很好的提供了可伸縮的運動輸入量,但是軸映射也可以映射常見的移動按鍵,如WASD,上下左右,來不斷輪詢遊戲行爲。


First, we will set up axis mappings for the W, A, S, and D keys.

首先,爲WASD設置軸映射。

  1. In the Edit menu, click on Project Settings.
  2. 選擇Edit中的 Project Settings
  3. Under the Engine heading on the left side of the Project Settings tab, click on Input.
  4. Engine標題下面找到Input.
  5. Under Bindings, click on the plus sign next to Axis Mappings (If nothing appears, click the arrow to the left of Axis Mappings).
  6. 在Binding下點擊Axis Mappings 加號(如果沒事時,點擊右邊的箭頭)。
  7. Type "MoveForward" into the text field that appears, then click on the arrow to the left of the text box to expand the axis binding options.
  8. 在編輯框中輸入 "MoveForward" ,點擊箭頭擴展選項。
  9. In the dropdown menu, select W. Your input settings should now look like the following:
  10. 在下拉列表中選擇W。你的輸入設置應該會如下圖所示:
Input wasd settings.png


6. Now, click on the plus sign next to MoveForward

點擊MoveForward旁邊的加號

7. In the second dropdown menu, select S. Type "-1" in the Scale field. Your input settings should now look like the following:

在第一個下拉菜單中選擇S,Scale中輸入-1,設置如下

Input wasd settings 2.png


8. Under Bindings, click on the plus sign next to Axis Mappings.

點擊Axis Mappings旁的加號.

9. Type "MoveRight" into the text field that appears, then click on the arrow to the left of the text box to expand the axis binding options. "MoveRight" .

10. In the dropdown menu, select D. Your input settings should now look like the following:

如添加“W”一樣添加“D”.

Input wasd settings 3.png


11. Under Bindings, click on the plus sign next to MoveRight.

點擊MoveForward旁邊的加號。

12. In the second dropdown menu, select A. Type "-1" in the Scale field. Your input settings should now look like the following:

如添加“S”一樣添加“A”.Scale設置-1.

Input wasd settings 4.png


13. Close the Project Settings menu.

關閉 Project Settings。

14. Switch to your project in Visual Studio.

切換到VS。

15. The Character class has a function called SetupPlayerInputComponent that is called when the PlayerController possesses the Character. We will override this function to bind our own handlers for the MoveForward and MoveRight axis mappings.

當PlayerController操縱Character的時候,Character類有一個名爲SetupPlayerInputComponent 方法被調用。我們將重寫該方法來綁定自己MoveForward 和MoveRight軸映射的處理程序 。

16. In FPSCharacter.h, add the following declaration under virtual void BeginPlay() override;

:FPSCharacter.h,在virtual void BeginPlay() override;下一行添加以下聲明:

    protected:
        virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;

17. We also want to declare our handler functions, so add these lines under the SetupPlayerInputComponent declaration inFPSCharacter.h and save the file.

聲明自己的處理方法,在FPSCharacter.h SetupPlayerInputComponent聲明的下一行添加以下代碼,保存。

    //handles moving forward/backward
    UFUNCTION()
    void MoveForward(float Val);
    //handles strafing
    UFUNCTION()
    void MoveRight(float Val);

UFUNCTION() Macro —— UFUNCTION () 宏

The UFUNCTION macro is used above each of these functions. By itself, the UFUNCTION macro makes the engine aware of these functions, so that they can be included in serialization, optimization, and other engine functionality. You may also have noticed the UCLASS macro above your new FPSGameMode and FPSCharacter class declarations, which does the same thing but for classes, and there is also a UPROPERTY macro for properties. There are a number of specifiers you can supply to these macros to change the function, class, and property behaviors in the engine, which can be found in ObjectBase.h.

UFUNCTION宏被用於上面的每個方法。通過自身,UFUNCTION宏使引擎意識到這些函數的存在,從而使它們可以被包含於序列化、優化和其他引擎功能。你可能也會在上面的FPSGameMode和FPSCharacter類聲明中注意到UCLASS宏爲類做同樣的事情,還有一個針對屬性的UPROPERTY宏。有許多修飾符供你提給宏以改變引擎中的方法、類以及屬性行爲,它們可以在ObjectBase.h找到。

After setting up our function dhoneclarations, we will implement them in FPSCharacter.cpp.

完成設置我們的方法聲明後,我們將在FPSCharacter.cpp實現它們。

1. First, we will define SetupPlayerInputComponent. The following lines set up the gameplay key bindings. Add them below the constructor in FPSCharacter.cpp.

首先,定義SetupPlayerInputComponent,下面代碼設置遊戲案件綁定,將他們添加到FPSCharacter.cpp中的構造函數的下方。

    void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* InputComponent)
    {
        // set up gameplay key bindings
        InputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
        InputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
    }

An InputComponent is a component that defines how to handle input data and can be attached to an actor that wants to receive input.

輸入組件定義瞭如何處理輸入數據,可以被附加到需要接受輸入的Actor上。

We also need to implement our MoveForward and MoveRight functions. In a typical FPS control scheme, the movement axes are camera-relative. That is, "forward" means "direction the camera is pointing", right means "to the right of the direction the camera is pointing", and so on. We will get the control rotation from the PlayerController. Also, since we want to move along the ground even while we are looking up or down (as opposed to trying to push into the ground), our MoveForward function will ignore the pitch component of the control rotation and restrict our input to the XY plane.

我們同樣需要實現 MoveForward 和 MoveRight方法。典型的FPS控制方案中,運動軸與相機相對。那就是說,前方代表相機指向的方向,右方代表相機指向方向的右邊,以此類推。我們將從PlayerController獲取control rotation.同樣,由於我們想在向上或向下看時沿着地面移動(而不是試圖進入地下)MoveForward 方法將會忽略control rotation的俯仰組件,並且限制我們對XY平面的輸入。
2. Add the following function to FPSCharacter.cpp:
添加以下代碼到 FPSCharacter.cpp:
    void AFPSCharacter::MoveForward(float Value)
    {
        if ( (Controller != NULL) && (Value != 0.0f) )
        {
            // find out which way is forward
            FRotator Rotation = Controller->GetControlRotation();
            // Limit pitch when walking or falling
            if (GetCharacterMovement()->IsMovingOnGround() || GetCharacterMovement()->IsFalling() )
            {
                Rotation.Pitch = 0.0f;
            }
            // add movement in that direction
            const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
            AddMovementInput(Direction, Value);
        }
    }


Our code for MoveRight is very similar, except we will move along a different axis of our control rotation. We also don't need to worry about zeroing the pitch in this case because pitching doesn't affect the Y direction vector.除了沿着不同的旋轉軸移動,MoveRight 代碼與之類似。我們無需擔心俯仰歸零的情況,因爲俯仰不影響Y方向向量。

3. Add the following function to FPSCharacter.cpp:

    void AFPSCharacter::MoveRight(float Value)
    {
        if ( (Controller != NULL) && (Value != 0.0f) )
        {
            // find out which way is right
            const FRotator Rotation = Controller->GetControlRotation();
            const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
            // add movement in that direction
            AddMovementInput(Direction, Value);
        }
    }

以下代碼添加到FPSCharacter.cpp:

Let's test out the Character now, and see how we can move throughout the level.

現在,讓我們測試下角色吧,看看我們是如在關卡中移動的。

1. Close Unreal Editor.2. Compile3. After the build finishes, open Unreal Editor, and then open FPSProject.4. Click on the Play In button in the Level Editor Toolbar. You should be able to move and strafe throughout the level, although your camera will be fixed in place.5. Press Escape to exit Play in Editor (PIE) mode.

運行方法如故

--------------------------------------------------------------------------------------------------------------

4.10 運行成功。

代碼如下:

FPSCharacter.h

  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #pragma once  
  4.   
  5. #include "GameFramework/Character.h"  
  6. #include "FPSCharacter.generated.h"  
  7.   
  8. UCLASS()  
  9. class MYFPSPROJECT_API AFPSCharacter : public ACharacter  
  10. {  
  11.     GENERATED_BODY()  
  12.   
  13. public:  
  14.     // Sets default values for this character's properties  
  15.     AFPSCharacter();  
  16.   
  17.     // Called when the game starts or when spawned  
  18.     virtual void BeginPlay() override;  
  19.       
  20.     // Called every frame  
  21.     virtual void Tick( float DeltaSeconds ) override;  
  22.   
  23. protected:  
  24.     // Called to bind functionality to input  
  25.     virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;  
  26.   
  27.     UFUNCTION()  
  28.         void MoveForward(float Val);  
  29.     //handles strafing  
  30.     UFUNCTION()  
  31.         void MoveRight(float Val);  
  32. };  
FPSCharacter.cpp
  1. // Fill out your copyright notice in the Description page of Project Settings.  
  2.   
  3. #include "MyFPSProject.h"  
  4. #include "FPSCharacter.h"  
  5.   
  6.   
  7. // Sets default values  
  8. AFPSCharacter::AFPSCharacter()  
  9. {  
  10.     // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.  
  11.     PrimaryActorTick.bCanEverTick = true;  
  12.   
  13. }  
  14.   
  15. // Called when the game starts or when spawned  
  16. void AFPSCharacter::BeginPlay()  
  17. {  
  18.     Super::BeginPlay();  
  19.     if (GEngine)  
  20.     {  
  21.         GEngine->AddOnScreenDebugMessage(-1, 5.f,FColor::Blue, TEXT("We are using FPSCharater"));  
  22.     }  
  23.       
  24. }  
  25.   
  26. // Called every frame  
  27. void AFPSCharacter::Tick( float DeltaTime )  
  28. {  
  29.     Super::Tick( DeltaTime );  
  30.   
  31. }  
  32.   
  33. // Called to bind functionality to input  
  34. void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)  
  35. {  
  36.     Super::SetupPlayerInputComponent(InputComponent);  
  37.     // set up gameplay key bindings  
  38.     InputComponent->BindAxis("MoveForward"this, &AFPSCharacter::MoveForward);  
  39.     InputComponent->BindAxis("MoveRight"this, &AFPSCharacter::MoveRight);  
  40.   
  41. }  
  42.   
  43. void AFPSCharacter::MoveForward(float Value)  
  44. {  
  45.     if ((Controller != NULL) && (Value != 0.0f))  
  46.     {  
  47.         // find out which way is forward  
  48.         FRotator Rotation = Controller->GetControlRotation();  
  49.         // Limit pitch when walking or falling  
  50.         if (GetCharacterMovement()->IsMovingOnGround() || GetCharacterMovement()->IsFalling())  
  51.         {  
  52.             Rotation.Pitch = 0.0f;  
  53.         }  
  54.         // add movement in that direction  
  55.         const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);  
  56.         AddMovementInput(Direction, Value);  
  57.     }  
  58. }  
  59.   
  60. void AFPSCharacter::MoveRight(float Value)  
  61. {  
  62.     if ((Controller != NULL) && (Value != 0.0f))  
  63.     {  
  64.         // find out which way is right  
  65.         const FRotator Rotation = Controller->GetControlRotation();  
  66.         const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);  
  67.         // add movement in that direction  
  68.         AddMovementInput(Direction, Value);  
  69.     }  
  70. }  

PS:等這系類教程翻譯並學習完了,再上傳源碼。以後就不像上面兩個兩樣上傳章節源碼了。

----------------------------------------------------------------------------------------------------

Mouse Camera Control —— 鼠標控制相機

Let's add the ability to look around and steer with the mouse.

讓我們添加拖動鼠標,環顧四周的功能吧。

First, let's set up axis mappings for Turn and LookUp.

首先,爲 Turn 和 LookUp設置軸映射。

1. In the Edit menu, click on Project Settings.

進入Project Settings

2. Under the Engine heading on the left side of the Project Settings tab, click on Input.

Project Settings中選擇Input。

3. Under Bindings, click on the plus sign next to Axis Mappings.

bingding下點擊加號添加軸映射。

4. Type "Turn" into the text field that appears, then click on the arrow to the left of the text box to expand the axis binding options.

輸入“Turn”文本,點擊它左側的箭頭擴展選項。

5. In the dropdown menu, select MouseX.

下拉菜單中選擇MouseX

6. Under Bindings, click on the plus sign next to Axis Mappings.

點擊Axis Mappings旁邊的加號。

7. Type "LookUp" into the text field that appears, then click on the arrow to the left of the text box to expand the axis binding options.

類似“Turn”設置“LookUp”.

8. In the dropdown menu, select MouseY and enter "-1" for Scale. Your input settings should now look like the following:

類似MouseX設置MouseY,起值設爲-1.設置圖如下:

Input mouse settings.png


9. Close the Project Settings menu.

關閉Project Settings

Now, let's add some code to handle those inputs.

現在,爲輸入控制添加代碼。

The Character class defines the two necessary functions for us: AddYawInput and AddPitchInput.

Character爲我們定義了兩個必要的方法:

If we wanted to do additional processing, such as adding support for sensitivity or axis inversion, we could provide our own functions to adjust the values before passing them to these functions, but in this case let's bind our inputs directly to them.

如果我們想添加一些如支持靈敏度和軸反轉的處理,我們可以在給這些方法傳遞參數前提供自己的函數調整這些值,但這種情況我們的輸入直接綁定它們。

1. Add the following lines to SetupPlayerInputComponent in FPSCharacter.cpp:

FPSCharacter.cpp中爲SetupPlayerInputComponent添加如下代碼:

   InputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
   InputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);

Because we only changed an existing function instead of making a new function, we can compile within the editor.
由於我們只是改變現有的方法而不是新建一個方法,因此我們可以在編輯器內直接編譯(PS:4.10 哪裏都可以編譯,這裏的意思是不用像MoveFoward那樣定義方法了。)。

1. Switch back to Unreal Editor, and click on the Compile button.
返回虛幻編輯器點擊編譯。

2. The Compiling C++ Code notification will pop up in the bottom right of the screen. Wait for it to finish - it will say Compile Complete and then fade out.
屏幕右下角會顯示Compiling C++ Code,他將提示Compile Complete並淡出。

Compiling in editor.png





3. Click on the Play In button in the Level Editor Toolbar. Now, you can control the camera direction with your mouse.
Play,你可以通過鼠標控制相機方向。

4. Press Escape to exit Play in Editor (PIE) mode.
Esc鍵退出。

----------------------------------------------------------------------
PS:4.10.2 親測成功。

--------------------------------------------------------------------------------------------------------------

Jumping —— 跳躍

Now, let's add jumping to our movement abilities. Our movement and camera control steps used axis mappings, which handle continuous inputs needed for those types of controls. There are also action mappings, which deal with inputs for discrete events.
現在,讓我們添加跳躍功能吧,我們的運動和相機控制步驟使用了軸映射,他們處理這類控制所需的連續輸入。這裏還有處理離散事件輸入的動作映射。


ActionMappings —— 動作映射

Map a discrete button or key press to a "friendly name" that will later be bound to event-driven behavior. The end effect is that pressing (and/or releasing) a key, mouse button, or keypad button directly triggers some game behavior.
一個離散按鍵映射到一個"friendly name" 後將會綁定到事件驅動行爲。它導致的結果是,點擊(釋放)按鍵、鼠標鍵或者鍵盤按鍵(key)會直接觸發一些遊戲行爲。

Let's add a new action mapping called Jump in the editor.
讓我們在編輯器添加一個Jump動作映射。

1. In the Edit menu, click on Project Settings.
打開Project Setting.

2. Under the Engine heading on the left side of the Project Settings tab, click on Input.
選擇Input.

3. Under Bindings, click on the plus sign next to Action Mappings.
Action Mappings旁邊點擊加號。

4. Click on the arrow to the left of Action Mappings to expand the Action Mappings settings.
點擊小箭頭擴展動作映射的設置。

5. Type "Jump" in the text field.
輸入文本。"Jump"

6. Expand the dropdown, and select Space Bar.
下拉選擇Space Bar。

Actionmapping jump.png


7. Close the Project Settings menu.
關閉Project Settings

Now we want to bind this action to some code that will cause our character to jump.
現在我麼想將動作綁定到可以控制角色跳躍的代碼。

If we look at Character.h, we can see there is jump support built in, tied to the bPressedJump variable. So all we need to do is set that flag to 1 when the jump action is pressed, and 0 when it is released. We need two functions to accomplish this.
Character.h中,我們可以看到Jump已被內置,它綁定在bPressedJump變量。所以我們要做的是在跳躍鍵按下設置爲1,釋放按鍵設置爲0。這需要兩個方法來完成。

1. In FPSCharacter.h, add the following public function declarations:
FPSCharacter.h,添加如下方法聲明。

   //sets jump flag when key is pressed
   UFUNCTION()
   void OnStartJump();
   //clears jump flag when key is released
   UFUNCTION()
   void OnStopJump();

2. In FPSCharacter.cpp, we can implement them very simply:
FPSCharacter.cpp,簡單的實現它們。

   void AFPSCharacter::OnStartJump()
   {
       bPressedJump = true;
   }
   void AFPSCharacter::OnStopJump()
   {
       bPressedJump = false;
   }

Finally, we need to bind the Jump action to our new functions.
最後,我們需要綁定跳躍動作到我們的新方法中。

3. In SetupPlayerInputComponent, add the following:
SetupPlayerInputComponent中,添加以下代碼:

   InputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::OnStartJump);
   InputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::OnStopJump);

Because we added new functions instead of just altering existing functions like in the previous step, we need to compile in Visual Studio instead of in the editor.
1. Close Unreal Editor.
2. Compile.
3. After the build finishes, open Unreal Editor, and then open FPSProject.
編譯方法照舊。

4. Click on the Play In button in the Level Editor Toolbar.
5. Press Spacebar to jump! You should now have a good set of starting movement controls, with WASD moving and strafing, camera control with the mouse, and jumping.
6. Press Escape to exit Play in Editor (PIE) mode.
點擊Play。
按下空格鍵跳躍。到此爲止,你會有WASD移動、鼠標控制相機和跳躍功能。
Esc退出

-----------------------------------------------------

4.10親測可行。
--------------------------------------------------------------------------------------------------------------

Adding a mesh to your Character —— 添加角色mesh

Now let's give ourselves a body in the world. The Character class creates a SkeletalMeshComponent object for us by default, so all it needs to know is which SkeletalMesh asset to use. Let's make a Blueprint of our FPSCharacter class so we can easily set this asset and manipulate any future components we might want to add. We'll start by importing a third person Skeletal Mesh. Eventually, we will set it up so that there is one mesh that the player sees, and one mesh that other players would see in a multiplayer mode.
現在,讓我們在虛擬世界中給我們自己添加個身體吧。Character類默認爲我們創建了一個SkeletalMeshComponent對象,所以只需知道的是去使用哪種SkeletalMesh資源。讓我們爲FPSCHaracter類創建一個藍圖,從而讓我們可以輕鬆的設置資源以及操作以後我們想添加的任何組件。

1. Download the following zip file, and unzip it to get the third person mesh file.
下載下面的ZIP文件,解壓活得第三人稱mesh文件(獲取FBX文件)。

Generic Male

2. Open Unreal Editor.
打開虛幻編輯器。

3. Right-click in the Content Browser, and select Import to /Game in the menu that appears.
在Content Browser中右鍵選擇Import to /Game 。

4. Navigate to wherever you saved the FBX file, then select it and click Open.
選擇你的FBX後點擊打開。

5. Open the Advanced dropdown and check Import Materials, then click on Import.
點擊Advanced下拉,勾選Import Materials,。(博主在4.10版本是直接拖拽FBX到Content的,跳出窗口默認選擇,然後import.)

6. Click on the Save icon in the Content Browser to save your new Skeletal Mesh and its associated assets.
 Content Browser點擊Save圖標來保存你新建的Skeletal Mesh,它會關聯資源。

Now, we can create a Blueprint of our FPSCharacter class and assign this new Skeletal Mesh to the SkeletalMeshComponent.
現在,我們可以創建FPSCharacter類的藍圖,指定新建的SkeletalMeshSkeletalMeshComponent

1. Right-click in the Content Browser and select New Folder. Name this new folder Blueprints.
Content Browser 新建名爲Blueprints的文件夾。

2. Double-click on the folder to open it.
雙擊打開文件夾。

3. Click on the New dropdown, and select Blueprint.
點擊New,選擇Blueprint。(也可以右鍵選擇)

New asset bp.png


4. Expand the Custom Class dropdown, and type "FPSCharacter" into the search box.
擴展開Custom Class,搜索FPSCharacter。(PS:4.10 的是叫做All Classes

Custom bp fpschar.png


5. Click on FPSCharacter to select it as the parent class for your new Blueprint and then click on Select.
選擇FPSCharacter作爲新建藍圖的基類,點擊Select.

6. Name this new Blueprint BP_FPSCharacter, then double-click its icon to open it.
藍圖命名爲BP_FPSCharacter,雙擊打開。

The Blueprint Editor will open in Components Mode, so we will be able to easily set our third-person mesh.
藍圖編輯器會以組件模式打開,你可以輕而易舉的看到第三人稱mesh.(PS:4.10打開藍圖可在左側上部看到,如下圖)


1. Click on the Mesh component in the Components tab.
在component選項卡中點擊Mesh組件。

Components tab.png


2. In the Details tab, scroll down to the Mesh section. Click on the dropdown that says None, then select your recently imported Skeletal Mesh asset. You may have to resize the Details tab to see this menu.
在Details選項卡,下滑到Mesh部分它顯示none.點擊下;希臘選擇你新導入的Skeletal Mesh資源。你可能需要調整Details 選項卡來看到這個菜單(PS:這裏應該是指……還是用圖來說明吧,見下圖)。

3. Align the SkeletalMeshComponent to the CapsuleComponent by setting its Z location to -88 in the Details tab.
在選項卡中通過設置它的Z值爲-88來使SkeletalMeshComponent對齊CapsuleComponent(膠囊體)。

Mesh move down.png


When using your own Skeletal Mesh assets, you may need to adjust them differently, but the overall goal is always to have the mesh contained within the CapsuleComponent, and facing the same direction that the ArrowComponent is pointing. This will ensure that your Character moves correctly through the world. You can also move components around with widgets in the Preview Viewport, rather than setting values in the Details tab.
使用你資源時,你可能需要不同程度上的調整它們,但整體上始終是要包含在CapsuleComponent裏面的的,並且面向方向與相同ArrowComponent 。這將確保你的角色在世界中正確移動。你也可以在Viewport中通過座標移動components,而不僅是在Details選項卡中設置值。

4. Compile and save your Blueprint, then close the Blueprint Editor.
編譯並保存你的藍圖,然後關閉。

Now we need to tell our GameMode to use our Blueprint class for the player pawn, instead of the FPSCharacter class we set earlier.
現在我們需要告訴我們的GameMode爲玩家pawn使用我們的藍圖類,使其替代早先我們設置的FPSCharacter類。

1. Switch to Visual Studio.
切換到VS。

2. Go to the FPSGameMode constructor in FPSGameMode.cpp, and replace the existing DefaultPawnClass assignment:
進入 FPSGameMode.cpp中的FPSGameMode構造函數,替換DefaultPawnClass的值。

   DefaultPawnClass = AFPSCharacter::StaticClass();

with the following code:
使用以下代碼:

   // set default pawn class to our Blueprinted character
   static ConstructorHelpers::FClassFinder<APawn> PlayerPawnObject(TEXT("Pawn'/Game/Blueprints/BP_FPSCharacter.BP_FPSCharacter_C'"));
   if (PlayerPawnObject.Class != NULL)
   {
       DefaultPawnClass = PlayerPawnObject.Class;
   }

This code will find the class generated by your blueprint and assign it as your default pawn class. (Note the "_C" suffix in the asset path, this is what distinguishes the actual class used by the game from the Blueprint asset, which is an editor-only concept.) At this point, you could also remove the #include "FPSCharacter.h" from the top of FPSGameMode.cpp, since you are no longer referring to the FPSCharacter C++ class.
這些代碼會找到你的藍圖產生的類,並使其成爲默認的pawn類。(注意資源路徑中帶“_C”的後綴,這是遊戲實際使用的類與藍圖資源之間唯一編輯器原則的區別,PS:這裏不大懂。),同時,你也可以在FPSGameMode.cpp頂部移除#include "FPSCharacter.h" (PS:可以註釋掉),因爲你不再需要關聯FPSCharacter類了。

Note that if you put your Blueprint in a different folder in the asset tree, you can get the full path by right-clicking on it in the Content Browser and selecting "Copy Reference". The full path will be placed on your clipboard for handy pasting.
注意:如果你把你的藍圖放在了不同的資源文件夾中,你可在內容瀏覽器右鍵選擇獲取完整路徑。完整路徑將放置在方便粘貼的剪貼板中。

1. Switch back to Unreal Editor, and click on the Compile button.
2. The Compiling C++ Code notification will pop up in the bottom right of the screen. Wait for it to finish - it will say Compile Complete and then fade out.
3. Click on the Play In button in the Level Editor Toolbar. If you move the camera around, you should be able to see your character's shadow.
4. Press Shift+F1 to regain your mouse cursor, then click on Eject in the toolbar. You are no longer possessing the character, so you can move the camera around freely and see your character's mesh.
5. Click on Stop to exit Play in Editor (PIE) mode.
編譯。
運行。
如果你移動攝像機,你會看到你的角色陰影。
按住Shift+F1 ,顯示鼠標光標,點擊工具欄上的Eject。你不在佔有角色,所以你可以自由一定相機看到你的角色mesh。
Esc退出。

Step7 ejected.png


--------------------------
4.10版本已測試成功。

--------------------------------------------------------------------------------------------------------------

Changing the Camera View —— 切換鏡頭

At the end of the previous step, the default camera is positioned inside the mesh's neck. Let's set up a proper camera that we can use to adjust the camera's properties such as location and field of view. We're going to do this by adding a CameraComponent to our FPSCharacter. First, let's add a property to the FPSCharacter to hold a reference to our CameraComponent.
在前面步驟的後面,默認相機是定位在mesh的脖子部位的。讓咱設置一個適當的相機,我們可以用它調整相機的位置和視野等屬性。

1. Go to FPSCharacter.h in Visual Studio and add the following to create a public property:
 FPSCharacter.h添加以下代碼:

   /** First person camera */
   UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
   UCameraComponent* FirstPersonCameraComponent;

We will also need to add a constructor to our FPSCharacter.h file.
我們需要爲 FPSCharacter.h添加構造函數。

   // Constructor for AFPSCharacter
   AFPSCharacter(const FObjectInitializer& ObjectInitializer);

We will create the actual component in the FPSCharacter constructor.
我們將在FPSCharacter構造函數創建實際組件。

2. Add the following code in FPSCharacter.cpp to create the CameraComponent and attach it to the CapsuleComponent.
FPSCharacter.cpp 中添加以下代碼來創建 CameraComponent,並附加到CapsuleComponent

   AFPSCharacter::AFPSCharacter(const FObjectInitializer& ObjectInitializer)
       : Super(ObjectInitializer)
   {
       // Create a CameraComponent 
       FirstPersonCameraComponent = ObjectInitializer.CreateDefaultSubobject<UCameraComponent>(this, TEXT("FirstPersonCamera"));
       FirstPersonCameraComponent->AttachParent = CapsuleComponent;
   }
   


Finally, let's adjust the camera's position to be a little above the character's eye location.
最後,調整相機位置到角色眼睛位置。

3. Add this to the constructor, after the component is created. You can tweak the camera's position in the BP_FPSCharacterBlueprint later as well, but this gives a good starting location for the CameraComponent. Also, you will only set the CameraComponent's location, not its rotation, because our earlier Turn and LookUp functions will control the camera's orientation.
當組件創建之後,添加下面代碼到構造函數中。你之後也可以在中調整相機位置,但這裏爲CameraComponent給出一個好的出事位置。同樣,你也可僅設置CameraComponent的位置量,而不是旋轉量,因爲早先我們的Turn和LookUp方法會控制相機的方向。

   // Position the camera a bit above the eyes
   FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 50.0f + BaseEyeHeight);
   // Allow the pawn to control rotation.
   FirstPersonCameraComponent->bUsePawnControlRotation = true;

Because we added a new property, we need to compile in Visual Studio instead of in the editor.
因爲我們添加了新的屬性,我們需要在VS中編譯。
1. Close Unreal Editor.
2. Compile.
3. After the build finishes, open Unreal Editor, and then open FPSProject.
4. Click on the Play In button in the Level Editor Toolbar.
編譯如之前所述。運行。(4.10直接編譯)

5. Your camera should be above the character's head now, and if you look down, you will be able to see the top of your character's head.
現在你的相機會在角色的頭頂上,如果你想下看,你會看到角色的頭頂。

6. Press Escape to exit Play in Editor (PIE) mode.
ESC退出

Adding a First Person Mesh —— 添加第一人稱Mesh

A common FPS approach is to use 2 separate meshes. One is the normal full-body mesh, used when seeing the character from third person but hidden when in first person. The second is a "weapon and hands" mesh that is attached to the camera and is visible only to the player when the player is in a first person perspective.
通常FPS設置了2個獨立的mesh.一種是全身mesh,在第三人稱看到角色時被用到,第一人稱時隱藏。第二種是綁定在相機的“武器和手”,當玩家處於第一人稱視角時可見。

To implement this, we'll keep the existing component named Mesh as our third person mesh and make a new SkeletalMeshComponent to be our first person mesh.
爲了實現它,我們會保留現有的名爲Mesh的第三人稱mesh組件,新建一個SkeletalMeshComponent作爲第一人稱mesh.

1. First add a public variable to FPSCharacter.h to keep a reference to this new mesh:
首先爲FPSCharacter.h添加新的public變量來關聯新的mesh.

    /** Pawn mesh: 1st person view (arms; seen only by self) */
    UPROPERTY(VisibleDefaultsOnly, Category=Mesh)
    USkeletalMeshComponent* FirstPersonMesh;

2. Then, in the constructor for FPSCharacter.cpp, we'll add code to create and configure this mesh after our code that configures the FirstPersonCameraComponent:

然後,在的構造函數中,於配置FirstPersonCameraComponent的後面,添加代碼創建並配置這個mesh。

    // Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
    FirstPersonMesh = ObjectInitializer.CreateDefaultSubobject<USkeletalMeshComponent>(this, TEXT("FirstPersonMesh"));
    FirstPersonMesh->SetOnlyOwnerSee(true);         // only the owning player will see this mesh
    FirstPersonMesh->AttachParent = FirstPersonCameraComponent;
    FirstPersonMesh->bCastDynamicShadow = false;
    FirstPersonMesh->CastShadow = false;

We are using SetOnlyOwnerSee here to indicate that this mesh is only visible to the "owning" player, in this case the PlayerController who has possessed this Character. We also set the mesh to be attached to the camera. Finally, we disable some environmental shadowing since seeing shadows of these camera-attached arms would look odd and destroy the illusion.

這裏我們使用來聲明這個mesh是僅對玩家擁有着可見的,這種情況下, PlayerController佔有Character。我們同樣把mesh附加到相機上。最後,我們關掉環境陰影,因爲與相機連接的手臂的陰影看起來會不和諧。

3. Finally, we have to change the settings for Mesh, the existing third person SkeletalMeshComponent. Add the following lines to the constructor to set its visibility so it is hidden from the owning player.

最後,我們需要爲Mesh改變設置——已存的第三人稱SkeletalMeshComponent。在構造函數中添加以下代碼來設置它的可見性,所以他會對所屬玩家隱藏。

    // everyone but the owner can see the regular body mesh
    Mesh->SetOwnerNoSee(true);

As before, we will set the mesh asset in the Blueprint, so let's compile and run the editor.

如之前一樣,我們會在藍圖中設置mesh,所以編譯運行編輯器吧。

1. Close Unreal Editor.

關閉虛幻編輯器(4.10省略該步驟)

2. Compile.

編譯

3. After the build finishes, open Unreal Editor, and then open FPSProject.

完成編譯後,打開FPSProject(4,10省略該步驟)

4. Download this zip file and unzip it to receive the first person mesh FBX file, which contains a SkeletalMesh with just arms.

下載你解壓ZIP文件獲得第一人稱mesh FBX文件,它只有手臂的 SkeletalMesh 。

First Person Skeletal Mesh

5. Navigate to the Game folder in the Content Browser.

到內容瀏覽器中的Game文件夾。

6. Right-click in the Content Browser, and select Import to /Game in the menu that appears.

右鍵點擊Content Browser選擇 Import to /Game。

7. Navigate to wherever you saved the FBX file, then select it and click Open.

進入你FBX所在的文件夾,選擇並點擊打開。(4.10可直接拖拽FBX)

8. Open the Advanced dropdown and make sure Import Materials is checked, then click on Import.

打開Advance下拉,確保勾選Import Materials ,點擊import.

If you receive an error about smoothing groups, you can disregard it. This mesh will still work to illustrate the first person mesh setup, and will work with the animations set up in a later step.
你可以忽略遇到的有關平滑組的錯誤。這個mesh依然仍然有用,用來說明第一人稱mesh的設置,以及後面步驟中的動畫設置。

1. Click on Save in the Content Browser to save your new Skeletal Mesh and its associated assets.

點擊Save 保存你的Skeletal Mesh,它會關聯資源。

2. Navigate back to the Blueprints folder in the Content Browser.

回到Content Browser中的Blueprints文件夾。

3. Open BP_FPSCharacter and switch to Components Mode.

打開BP_FPSCharacter ,切換到Components Mode。(4.10直接打開就行了)

(NOTE: There is an additional step required as a workaround to an current issue we are looking into. To be able to find the FirstPersonMesh in the component list, you will need to delete the BP_FPSCharacter blueprint and recreate it. After doing this you can continue with step 4.)

(注意:我們在這裏使用了一個額外的步驟解決當前我麼正在調查的問題。爲了能在component列表中找到FirstPersonMesh,你需要刪除BP_FPSCharacter藍圖重建它。之後你可以繼續步驟4.)PS :4.10不需重建藍圖,已測試。

4. Find the new FirstPersonMesh we added. Notice that it is a child of the FirstPersonCameraComponent, so it will always be attached to the camera. You may have to expand the FirstPersonCameraComponent dropdown.

找到我們添加的FirstPersonMesh,注意他是FirstPersonCameraComponent的子類,因此它會始終附着於相機。你可能需要打開FirstPersonCameraComponent擴展。

You may encounter an issue where the new FirstPersonMesh and FirstPersonCameraComponent do not appear in your blueprint. If this happens to you, you can remove the blueprint BP_FPSCharacter and create it again as described above, and the new properties will appear.
你可能會在藍圖中找不到FirstPersonMesh 和 FirstPersonCameraComponent。如果是這樣,你可以如上面說的移除並重建BP_FPSCharacter藍圖,這樣它們就會出現了。
Component listing.png


5. Click on the FirstPersonMesh component in the Components tab.

 Components選項卡中點擊FirstPersonMesh

6. In the Details tab, scroll down to the Mesh section. Click on the dropdown that says None, then select your recently imported Skeletal Mesh asset. You may have to resize the Details tab to see this menu. Now, the arms should appear in the Viewport, although you may have to zoom out to see them.

Details選項卡中,下滑到 Mesh部分。點擊None選擇新導入的Skeletal Mesh。你可能需要調整Details的大小來找到這個選項。現在,手臂會出現在Viewport,雖然你可能需要縮小才能看到它們的。(PS:感覺應該是放大吧)PS:博主在這裏手臂沒出來,於是關掉了藍圖,在虛幻編輯器編譯一下,重新打開藍圖就出現了。

Arms just added.png


7. To adjust the relative transform so the arms appear on the camera, set the Location to {240,0,35} and the Rotation to {-180, 50, -180}. You will readjust this position after the arms are animated, but for now, this position lets you see that you are using this first person mesh when playing.

爲了調整相關的位置使手臂出現在相機的面前,設置Location爲 {240,0,35},Rotation爲 {-180, 50, -180}。當手臂動起來的後你需要重新調整位置。但是現在,這個位置讓你看到了遊戲運行時,你正在使用第一人稱mesh.

Arms adjusted.png


8. Compile and Save your Blueprint, then close the Blueprint Editor.

編譯,保存,關閉藍圖。

9. Click on the Play In button in the Level Editor Toolbar.

點擊Play.

10. At this point, you will no longer be able to see the third person SkeletalMesh, but you will be able to see the disembodied arms of the first person SkeletalMesh.

這裏,你在也無法看到第三人稱SkeletalMesh,但你能看到第一人稱的虛擬手臂SkeletalMesh

Step9 arms.png


11. Press Shift+F1 to regain your mouse cursor, then click on Eject in the toolbar. You are no longer possessing the character, so you can move the camera around freely and see both the third person and the first person meshes.

按下Shift+F1 重現鼠標光標,點擊Eject,你不再佔據角色,依次你可以自由移動相機,同時看到第一人稱和第三人稱的mesh.

Step9 ejected.png


12. Press Escape to exit Play in Editor (PIE) mode.

ESC退出

-----------------------------------------

4.10測試成功。

--------------------------------------------------------------------------------------------------------------

Adding Projectiles and Shooting —— 添加子彈與射擊

Now that the character is set up, let's implement a simple projectile weapon - when you fire, a simple grenade-like projectile will shoot from the center of the screen and fly until it hits the world. While we have the editor open, let's add an input and create a new code class for our projectile.

既然角色已經建立起來,那麼讓咱實現簡單的子彈發射吧。當你開火時,會有簡單的類似子彈的東西從屏幕射擊知道與世界中的物體碰撞。打開編輯器,爲我們的子彈添加輸入和代碼類。

1. In the Edit menu, click on Project Settings.

進入Project Settings

2. Under the Engine heading on the left side of the Project Settings tab, click on Input.

進入Input選項

3. Under Bindings, click on the + next to Action Mappings.

點擊Action Mappings旁邊的+

4. Click on the arrow to the left of Action Mappings to expand the Action Mappings settings.

點擊Action Mappings左邊的擴展箭頭

5. Type "Fire" in the text field.

輸入文本"Fire"

6. Expand the dropdown, and select Left Mouse Button.

下拉選擇 Left Mouse Button

7. Close the Project Settings menu.

關閉Project Settings

Now let's create the projectile class.

現在,讓我們創建子彈類。

1. Go to File > Add Code to Project.

選擇。

2. Choose Actor, then click Next.

選擇Actor類,點擊下一步。

3. Name your new class FPSProjectile, then click on Create.

類名命名爲FPSProjectile,點擊Create

4. Click on Yes to open the class in Visual Studio for editing.

點擊Yes在VS中打開類。

5. Visual Studio will prompt you asking to reload the project, since the C++ Class Wizard modified it. Select Reload.

VS會提示是否重新加載項目,因爲C++類嚮導修改了他。選擇reload.

First, we should decide on a simplified physical representation to use for collision and simulation. For our case, let's use a USphereComponent.

首先,我們決定簡化用於碰撞和仿真的物理表示。在我們的案例中,我們使用USphereComponent.

1. Add a reference to this component in your FPSProjectile class declaration in FPSProjectile.h.

 FPSProjectile.h FPSProjectile聲明中添加組件引用。

    /** Sphere collision component */
    UPROPERTY(VisibleDefaultsOnly, Category=Projectile)
    USphereComponent* CollisionComp;

2. Add a constructor to FPSProjectile.h.

FPSProjectile.h添加構造函數聲明。

    AFPSProjectile(const FObjectInitializer& ObjectInitializer);

3. Create the component in the FPSProjectile constructor in FPSProjectile.cpp. We'll make it the root component since the simulation will drive it, and we can attach visual components to it later in a Blueprint.
FPSProjectile構造函數中創建組件。由於simulation驅使它的需要,我們將它設爲根組件,然後我們可以在之後的藍圖中將可視化組件附件到它上面。

    AFPSProjectile::AFPSProjectile(const FObjectInitializer& ObjectInitializer)
        : Super(ObjectInitializer)
    {
        // Use a sphere as a simple collision representation
        CollisionComp = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("SphereComp"));
        CollisionComp->InitSphereRadius(15.0f);
        RootComponent = CollisionComp;
    }

UE4 comes with a ProjectileMovementComponent that can be used to easily do simple ballistic-style movement, so let's add that to FPSProjectile.

UE4有一個可以做簡單彈道運動的ProjectileMovementComponent ,因此我們將它添加給FPSProjectile.

1. First, add a public reference in your FPSProjectile class declaration in FPSProjectile.h.

首先,在FPSProjectile類聲明中,添加public 相關變量。

    /** Projectile movement component */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Movement)
    UProjectileMovementComponent* ProjectileMovement;

2. Then, add the following lines to the FPSProjectile constructor in FPSProjectile.cpp to create this component:

然後,在FPSProjectile.cpp的構造函數中添加以下代碼來創建組件。

    // Use a ProjectileMovementComponent to govern this projectile's movement
    ProjectileMovement = ObjectInitializer.CreateDefaultSubobject<UProjectileMovementComponent>(this, TEXT("ProjectileComp"));
    ProjectileMovement->UpdatedComponent = CollisionComp;
    ProjectileMovement->InitialSpeed = 3000.f;
    ProjectileMovement->MaxSpeed = 3000.f;
    ProjectileMovement->bRotationFollowsVelocity = true;
    ProjectileMovement->bShouldBounce = true;
    ProjectileMovement->Bounciness  = 0.3f;

We've also set a few properties here to influence the simulation, the most important of which is the UpdatedComponent.

這裏我們設置了幾個屬性來影響仿真,其中最重要的是UpdatedComponent。

Looking ahead, we're also going to want a function to "launch" our projectile by setting its initial velocity.

往後一點,我們也想要一個可以通過設置初始速度的方法來發射我們的子彈。

1. Declare a public function in the FPSProjectile class declaration in FPSProjectile.h:

FPSProjectile.hFPSProjectile類聲明中public方法。

    /** inits velocity of the projectile in the shoot direction */
    void InitVelocity(const FVector& ShootDirection);

2. Implement the function in FPSProjectile.cpp by adding the following definition after the constructor.

    void AFPSProjectile::InitVelocity(const FVector& ShootDirection)
    {
        if (ProjectileMovement)
        {
            // set the projectile's velocity to the desired direction
            ProjectileMovement->Velocity = ShootDirection * ProjectileMovement->InitialSpeed;
        }
    }

Note that our projectile's speed is defined in the ProjectileMovementComponent, so we only need to supply a launch direction.

注意子彈速度已在ProjectileMovementComponent中定義,因此我們只需提供發射方向。

Finally, we will add code to the FPSCharacter so that when the Fire input is pressed, it will launch a projectile. As before, we will declare a public function called OnFire that we will bind to the Fire input we defined earlier.

最後,爲FPSCharacter添加代碼,從而當開火輸入按下時,子彈會被髮射。在此之前,我們會聲明一個綁定到早先我們聲明的Fire input的public的OnFire方法。

1. In FPSCharacter.h, add this function to the class declaration:

FPSCharacter.h中,添加方法聲明:

    //handles firing
    UFUNCTION()
    void OnFire();

2. In the FPSCharacter.cpp, add the following to SetupPlayerIputComponent to bind the Fire action to our new OnFire function.

FPSCharacter中添加代碼到SetupPlayerIputComponent綁定開火動作到我們的OnFire方法。

 InputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::OnFire);

There are two points to consider for the OnFire implementation. We know we want to spawn an FPSProjectile actor, so we have to define:
OnFire的實現需要考慮兩點。我們知道我們想要生成一個FPSProjectile actor,納悶我們需要定義:

  • Where to spawn the projectile
    哪裏產生子彈。
  • The projectile class so the FPSCharacter (and its derived Blueprint) will know what projectile to spawn.
    子彈類,從而讓FPSCharacter(及其派生藍圖)知道產生什麼子彈。


To determine a spawn location, we'll use a camera-space offset vector as an editable parameter, so we can set and tweak it in our BP_FPSCharacter Blueprint. We can then calculate an initial location for the projectile based on this data.
爲了確定產生地點,我們將使用相機的空間偏移量作爲可編輯參數,從而使我麼可以在BP_FPSCharacter藍圖中設置和調整它。我們可以在數據的基礎上爲子彈計算之後的初始位置。

1. Add the following to the FPSCharacter class declaration in FPSCharacter.h:
FPSCharacter.hFPSCharacter類聲明中添加以下代碼。(PS:這裏吧FPSCharacter錯搞成了FPSProjectile,害博主調試蛋疼了半天


    /** Gun muzzle's offset from the camera location */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
    FVector MuzzleOffset;

The EditAnywhere specifier allows you to change the value of the muzzle offset either within the Defaults mode of the Blueprint Editor, or within the Details tab for any instance of the character. The BlueprintReadWrite specifier allows you to both get and set the value of the muzzle offset within a Blueprint.

EditAnywhere修飾符允許你在藍圖編輯器的默認模式或者任何角色實例的Details選項卡中更改炮口偏移量。BlueprintReadWrite 修飾符允許你在藍圖中讀寫炮口偏移值。(PS:炮口偏移有點怪怪的)

Let's also introduce a projectile class as an editable parameter. This will allow us to later specify a Blueprint derived from FPSProjectile as the projectile we want to spawn.

讓我們介紹作爲可編輯參數的子彈類。這將使我們在之後指定作爲我們所想產生的子彈、繼承自FPSProjectile的藍圖。

1. Add the following to the FPSCharacter class declaration in FPSCharacter.h as well:

    /** Projectile class to spawn */
    UPROPERTY(EditDefaultsOnly, Category=Projectile)
    TSubclassOf<class AFPSProjectile> ProjectileClass;

FPSCharacter.hFPSCharactere類聲明中添加以下代碼

Here, we use the EditDefaultsOnly specifier, which means that you will only be able to set the projectile class as a default on the Blueprint, not on each instance of the Blueprint.這裏,我們使用 EditDefaultsOnly修飾符,他可以讓我們在特定藍圖默認只能寫入子彈類,而不是每個藍圖都有。

Our OnFire function will involve several steps.在我們的OnFire方法將會射擊到幾個步驟。

  • Since our projectile spawn location is derived in camera space, we find the camera transform before calculating the spawn location.因爲我們的子彈的產生位置是由相機空間驅使的,我們可以在計算子彈的產生位置前找到相機的位置信息。
  • We attempt to spawn the projectile.嘗試產生子彈。
  • Finally, we give it an initial velocity using the function we defined.最後,我們通過定義的函數給它初始速度。

1. Add the following function to FPSCharacter.cpp:

FPSCharacter.cpp添加以下方法。

    void AFPSCharacter::OnFire()
    {
        // try and fire a projectile
        if (ProjectileClass != NULL)
        {
            // Get the camera transform
            FVector CameraLoc;
            FRotator CameraRot;
            GetActorEyesViewPoint(CameraLoc, CameraRot);
            // MuzzleOffset is in camera space, so transform it to world space before offsetting from the camera to find the final muzzle position
            FVector const MuzzleLocation = CameraLoc + FTransform(CameraRot).TransformVector(MuzzleOffset);
            FRotator MuzzleRotation = CameraRot;
            MuzzleRotation.Pitch += 10.0f;          // skew the aim upwards a bit
            UWorld* const World = GetWorld();
            if (World)
            {
                FActorSpawnParameters SpawnParams;
                SpawnParams.Owner = this;
                SpawnParams.Instigator = Instigator;
                // spawn the projectile at the muzzle
                AFPSProjectile* const Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
                if (Projectile)
                {
                    // find launch direction
                    FVector const LaunchDir = MuzzleRotation.Vector();
                    Projectile->InitVelocity(LaunchDir);
                }
            }
        }
    }


2. Add an #include at the top of FPSCharacter.cpp, since we're using FPSProjectile from within FPSCharacter.由於我們在FPSCharacter.cpp中添加#include頭文件。

 #include "FPSProjectile.h"

3. Close Unreal Editor.
4. Compile.
5. After the build finishes, open Unreal Editor, and then open FPSProject.
編譯。

Now let's finalize our projectile by creating a Blueprint and adding a mesh so we can see the effect of shooting our projectile.
最後,讓我們通過創建藍圖、添加可以看到射擊效果的mesh來完成我們的子彈。

6. Download this zip file and unzip it to receive the sphere FBX file, which contains the StaticMesh you will use for your projectile.
下載並解壓ZIP活得球形FBX,它包含了你需要的子彈StaticMesh.

Sphere Mesh

7. Navigate to the Game folder in the Content Browser.
8. Right-click in the Content Browser, and select Import to /Game in the menu that appears.
9. Navigate to wherever you saved the FBX file, then select it and click Open.
10. Open the Advanced dropdown and make sure Import Materials is checked, then click on Import.

If you receive an error about smoothing groups, you can disregard it. This mesh will still work to illustrate the first person mesh setup, and will work with the animations set up in a later step.

11. Click on Save in the Content Browser to save your new StaticMesh.
12. Navigate back to the Blueprints folder in the Content Browser, then right-click in the Content Browser and create a new Blueprint.
13. Expand the Custom Classes dropdown and search for FPSProjectile, then select that as the parent class for your Blueprint.
14. Name your new Blueprint BP_FPSProjectile, then double-click it to open it in the Blueprint Editor.
導入FBX,新建名爲 BP_FPSProjectile類型爲FPSProjectile的藍圖並打開(詳細過程之前有翻譯)。

15. To add a child StaticMeshComponent to the root SphereComponent, click on CollisionComp in the Components tab, then select Static Mesh from the Add Component dropdown.
爲了添加 子StaticMeshComponent 給根 SphereComponent,在Components選項卡中CollisionComp點擊,從Add Component選擇Static Mesh

16. Name this new component ProjectileMesh.
新組件命名ProjectileMesh

 (PS:4.10截圖)

17. Set its Static Mesh asset to your sphere StaticMesh using the dropdown menu under Mesh in the Details panel.
在Details中的mesh部分設置你自己的sphere StaticMesh。

Note that if you are making a multiplayer game, that you must also uncheck "Initial Velocity in Local Space" in the "MovementComp" Component in order for this projectile to replicate correctly over a server.
注意:如果你創建的是多人遊戲,你不需要勾選 "MovementComp" Component中的"Initial Velocity in Local Space",從而讓服務器能正確的複製子彈。

18. Set the scale to 0.09 in X, Y, and Z.
設置XYZ的比例爲0.9.

Clicking on the the lock icon locks all three axes so they preserve their relative scale.
點擊鎖定圖標鎖定三條軸,從而使他們保持相應的規模。

19. Set the ProjectileMesh's Collision Presets value to NoCollision, since we're using the SphereComponent for collision and not this Static Mesh.
設置ProjectileMesh的Collision Presets(碰撞預設)值爲 NoCollision(無碰撞),因爲我們爲碰撞使用了SphereComponent而不是它的Static Mesh.

20. Compile and Save your Blueprint, then close the Blueprint Editor.
編譯保存你的藍圖,然後關閉。

21. Now open BP_FPSCharacter for editing, and open Defaults Mode.
打開編輯BP_FPSCharacter,打開Defaults Mode。

22. Find the Projectile Class property and set it to BP_FPSProjectile.
找到Projectile Class 屬性,並將其設置爲BP_FPSProjectile。

23. Set the MuzzleOffset property to {100, 0, 0} in order to spawn the projectile slightly in front of the camera.
設置MuzzleOffset屬性爲{100, 0, 0},以使得子彈在相機前方產生。

Defaults-Muzzle-Projectile.png


24. Compile and Save your Blueprint, then close the Blueprint Editor.
編譯保存你的藍圖,然後關閉。

25. Click on the Play In button in the Level Editor Toolbar.
點擊Play運行。

26. Left-click to fire your projectiles
鼠標右鍵開火發射子彈。

Projectiles pie.png


27. Press Escape to exit Play in Editor (PIE) mode.
ESC退出。

----------------------------------------------

4.10親測成功   就是自己翻譯錯了 ,調試半天沒找到問題,蛋疼。


--------------------------------------------------------------------------------------------------------------

Projectile Collision and Lifetime —— 子彈碰撞與生命週期

After adding our projectiles, there are two interesting things to notice that we should address.
完成子彈添加後,有兩個有趣的事情值得去注意,且我們應該去解決。

  • The projectiles live forever, as evidenced by the fact that they stay forever in the Scene Outliner.
    子彈永遠存在,作爲證明,可以在Scene Outliner看到它們一直存在着。
  • The projectiles don't collide with anything.
    子彈無法與任何事物碰撞。

Fortunately, all Actors in UE4 can have a limited lifespan, controlled by the InitialLifeSpan property.
幸運的是,在UE4中所有的Actor可有生命限制,它由InitialLifeSpan屬性控制。

1. Add the following lines to the FPSProjectile constructor to set the projectile's lifespan. You could also modify the Initial Life Span default in the BP_FPSProjectile Blueprint.
FPSProjectile藍圖中修改初始生命週期。

  // Die after 3 seconds by default
   InitialLifeSpan = 3.0f;
(PS:使用代碼無法實現生命週期,使用藍圖可以。推測可能是藍圖默認無限生命週期覆蓋了代碼實現的生命週期,以後再做討論。)
Life span default.png


UE4 comes with several useful collision channels, but also provides several customizable channels that game projects can use. Let's define a custom channel for projectiles, so everything can explicitly choose how to interact with a projectile in our game.
UE4帶有幾個有用的碰撞通道,同時也提供了幾個遊戲項目可使用的自定義通道。讓我們爲子彈定義一個自定義通道,使得遊戲中的一切事物可以選擇如何與子彈交互。

1. To customize a channel, open the Project Settings and select Collision.
打開Project Setting,選擇Collision,進行通道自定義。

Collision-Settings.png


2. Select New Object Channel... to make a new collision channel. Name this Projectile and be sure the Default Response is set to Block
選擇New Object Channel... to創建新的碰撞通道。命名爲Projectile ,確保Default Response爲Block。

3. Now select New...under Preset. Name this one Projectile as well. Set the settings for this collision preset as shown in the image below.
 Preset下面選擇 New...。同樣命名一個FPS

Preset-Collision-Settings.png


This profile means that the projectile will be blocked by Static Actors, Pawns, Dynamic Actors, Actors simulating Physics, Vehicles, and Destructible Actors.
此配置意味着子彈會被Static Actor, Pawns, Dynamic Actors, Actors simulating Physics, Vehicles, and Destructible Actors限制。

Now we'll set our projectile to use this profile.
現在,我們會設置我們的子彈使用這個配置。

1. In the FPSProjectile constructor in FPSProjectile.cpp, add the following line after the creation of CollisionComp.
 FPSProjectile.cpp的FPSProjectile 構造函數中,在創建後面添加以下代碼。

   CollisionComp->BodyInstance.SetCollisionProfileName("Projectile");

2. Close Unreal Editor.
3. Compile.
編譯

In the next step, we will set up how the projectile interacts with objects that it collides with.
在下一個步驟中,我們將設置子彈是如何與被碰撞的對象進行交互的。

--------------------------------------------------------------------------------------------------------------

Projectiles Interacting with the World —— 子彈與世界的交互

Now that we can detect our projectile's collision interactions, we can determine how to respond to them. In our projectile collision settings, we've set our interactions to be Blocks, so let's add a function to FPSProjectile called OnHit to respond to these events.
現在我們可以檢測子彈的碰撞,我們可以決定做出何種反應。在子彈碰撞提的設置中,我們設置了交互方式爲Blocks,讓我們爲FPSProjectile添加OnHit方法作爲響應事件。

1. In the FPSProjectile class definition, add the following function declaration:
FPSProjectile類定義中,添加以下方法聲明。

   /** called when projectile hits something */
   UFUNCTION()
   void OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);

Now, we will implement OnHit with functionality to add a physics impulse to whatever the projectile hits.
現在我們實現OnHit方法來爲任何子彈碰撞的物體添加物理脈衝。

1. Add the following to FPSProjectile.cpp:
FPSProjectile.cpp添加以下代碼。

   void AFPSProjectile::OnHit(AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
   {
       if ( OtherActor && (OtherActor != this) && OtherComp )
       {
           OtherComp->AddImpulseAtLocation(ProjectileMovement->Velocity * 100.0f, Hit.ImpactPoint);
       }
   }

Lastly, we need to hook this function to the projectile's SphereComponent's OnComponentBeginOverlap delegate.
最後,我們需要將這個方法綁定到 SphereComponent's OnComponentBeginOverlap 委託。

1. In the FPSProjectile constructor, add the following after CollisionComp is created.
FPSProjectile 構造函數中,在構建CollisionComp的後面添加以下代碼。

   CollisionComp->OnComponentHit.AddDynamic(this, &AFPSProjectile::OnHit);

2. Compile.
3. After the build finishes, open Unreal Editor, and then open FPSProject.
編譯

4. Select the SM_Template_Map_Floor floor StaticMesh.
選擇SM_Template_Map_Floor 地面StaticMesh(PS:直接複製World Outline中的floor ,粘貼得到floor2)

5. Copy and paste the floor mesh, then rescale the copy to {0.2, 0.2, 3.0}.
複製粘貼 floor mesh,複製體縮放到{0.2, 0.2, 3.0}。(PS:複製地面構建一個立方體,注意設置movable,以及勾選 Smulate Physics)

6. Position the mesh copy at {-230, 0, 160}.
複製體位置設爲{-230, 0, 160}.

7. Scroll down to the Physics section and check Simulate Physics.
下滑到Physics 部分,勾選Simulate Physics

8. Save your map.
保存你的地圖。

9. Click on the Play In button in the Level Editor Toolbar.
點擊Play運行。

10. Left-click to fire your projectiles and move the cube around your level. Your projectiles are now complete!
右鍵發射子彈,正方體會被彈動。你的子彈已完成功能。

Projectile box.png


11. Press Escape to exit Play in Editor (PIE) mode.
ESC退出。
--------------------------------------------------------------------
4.10親測成功,需要改動部分已在文中PS中註明。

Adding Crosshairs —— 添加十字準心

Now that you are able to shoot projectiles while playing your game, let's add a HUD with crosshairs to show where you are aiming.
既然你已經可以在遊戲中射擊了,那就讓給我們添加一個用來瞄準的十字準心HUD

1. Download the following file, and unzip it to get the crosshair image crosshair.TGA.
下載並解壓ZIP文件,獲取十字準心圖片—— crosshair.TGA.

Crosshair

2. In Unreal Editor, navigate to the Game folder in the Content Browser.
3. Right-click in the Content Browser, and select Import to /Game in the menu that appears.
4. Navigate to wherever you unzipped the crosshair.TGA file, then select it and click Open.
5. Click on Save in the Content Browser to save your new asset.
導入crosshair.TGA。保存。(與導入FBX類似)

UE4 comes with a basic HUD class we can extend, so let's add a new class derived from that.
UE4帶有基礎的HUD類,讓我們爲其創建一個派生類。

1. Go to File > Add Code to Project.
2. Select HUD as the parent class for your new class, and click Next.
3. Name your new class FPSHUD, then click on Create.
4. Click on Yes to open the class in Visual Studio for editing.
5. Visual Studio will prompt you asking to reload the project, since the C++ Class Wizard modified it. Select Reload.
創建類型爲HUD名爲FPSHUD 的類。

What we want to do here is to draw a crosshair icon on the center of the screen. First, we need a reference to our texture asset.
我們想要做的是使十字準心圖標至於屏幕中間。首先,我們需要關聯貼圖資源。

1. First we must set up the constructor for this new class. Place the following code in FPSHUD.h, under GENERATED_BODY().
首先我們需要FPSHUD.h中GENERATED_BODY()的下面爲新類構建構造函數。

AFPSHUD(const FObjectInitializer& ObjectInitializer);

2. Next we need to implement the constructor. Place the following code in FPSHUD.cpp.在FPSHUD.cpp實現構造函數。

AFPSHUD::AFPSHUD(const FObjectInitializer& ObjectInitializer)
    :Super(ObjectInitializer)

3. Add the following to the FPSHUD class definition in FPSHUD.h. We're only going to use this internally to this class, so let's make it private.FPSHUD.h中聲明以下代碼。由於它只供類內部使用,因而設爲private類型。

private:
    /** Crosshair asset pointer */
    UTexture2D* CrosshairTex;


4. We can then get a reference to our desired asset in the FPSHUD constructor.我們可以在FPSHUD構造函數中關聯我們所想要的資源。

As a reminder, you can get the asset path to your texture in the editor by right clicking the asset in the Content Browser and selecting Copy Reference.提醒下,你可以在Content Brower右鍵貼圖中的Copy Reference獲取資源路徑。

AFPSHUD::AFPSHUD(const FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer)
{
    // Set the crosshair texture
    static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("Texture2D'/Game/crosshair.crosshair'"));
    CrosshairTex = CrosshairTexObj.Object;
}

The HUD base class has a virtual function called DrawHUD that we can override to add our custom drawing code and draw the crosshairs on the screen.HUD基類有一個叫DrawHUD的虛方法,我們可以重寫添加我們自定義的繪製代碼,將十字準心繪製到屏幕上。

1. Add a function declaration to the FPSHUD class declaration, below GENERATED_UCLASS_BODY():在FPSHUD類聲明中GENERATED_UCLASS_BODY()下面添加以下方法聲明。

/** Primary draw call for the HUD */
    virtual void DrawHUD() OVERRIDE;


2. Implement the DrawHUD override in FPSHUD.cpp.在FPSHUD.cpp實現DrawHUD重寫。

  void AFPSHUD::DrawHUD()
    {
        Super::DrawHUD();
        // Draw very simple crosshair
        // find center of the Canvas
        const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f);
        // offset by half the texture's dimensions so that the center of the texture aligns with the center of the Canvas
        const FVector2D CrosshairDrawPosition( (Center.X - (CrosshairTex->GetSurfaceWidth() * 0.5)),
            (Center.Y - (CrosshairTex->GetSurfaceHeight() * 0.5f)) );
        // draw the crosshair
        FCanvasTileItem TileItem( CrosshairDrawPosition, CrosshairTex->Resource, FLinearColor::White);
        TileItem.BlendMode = SE_BLEND_Translucent;
        Canvas->DrawItem( TileItem );
    }

Finally, we need to tell our GameMode to use our custom HUD class when creating players.最後,我們需要在創建玩家的時候在告訴GameMode使用自定義的HUD。

1. In The FPSGameMode constructor, add:FPSGameMode構造函數中添加:

 HUDClass = AFPSHUD::StaticClass();

2. Add an include statement at the top of FPSGameMode.cpp.FPSGameMode.cpp添加頭文件:

   #include "FPSHUD.h"

3. Close the editor, build FPSProject, and open the editor with FPSProject one more time. This is the last step of the tutorial that utilizes Visual Studio, so you can close it now.
編譯。

4. Play your game in the editor. At this stage, you can move around, jump, control the camera, and shoot projectiles that interact with physics objects!
運行遊戲。你可以移動、跳躍、切換鏡頭、射擊並交互物理對象。

Step13 crosshairs.png

-------------------------
4.10 測試成功
--------------------------------------------------------------------------------------------------------------

Animating Your Character —— 讓你的角色動起來

Now let's get some animation into our game, by animating the first person arms we added a few steps back.
現在讓我們爲遊戲添加點動畫,讓之前添加的第一人稱手臂動起來。

1. Download the following file, and unzip it to get the five animations we will be working with in this step.
下載解壓ZIP,獲取5個動畫。

Animations

2. Back in the editor, navigate to the Game folder in the Content Browser. Right-click in the Content Browser and create a new folder called Animations.
3. Open the Animations folder, then right-click and select Import to /Game/Animations.
4. Navigate to the location you saved the five animations to, select all five, and then click on Open.
類似導入FBX導入五個動畫到新建的
Animations文件夾中。

5. Select HeroFPP_Skeleton under the Select Skeleton heading, then click on Import.
Select Skeleton標題下選擇HeroFPP,點擊Import.(PS:4.10位置有點不同)

Anim import.png


6. Repeat for the other four FBX Import Options prompts.
重複設置其他四個FBX Import Options提示。

7. Click on Save in the Content Browser to save your new assets.
點擊Content Browser裏的Svae保存資源。

Now that we have our assets imported, we need to create an Animation Blueprint.
既然已導入資源,我們需要創建一個動畫藍圖。

1. Right click and select Animation > Animation Blueprint.
右鍵選擇Animation > Animation Blueprint.

2. Choose AnimInstance as the Parent Class and choose /Game/HeroFPP_Skeleton as the Target Skeleton.
選擇AnimInstance作爲基類,選擇/Game/HeroFPP_Skeleton作爲Target Skeleton。

Create animation bp fps tutorial.png


3. Name it Arms_AnimBP and open it for edit.
命名爲Arms_AnimBP並打開。

Looking at our animation data, we have 5 animations to hook up:
瀏覽我們的動畫數據,有5個動畫連接。(PS:個人截圖如下)

  • Idle: When standing still
  • Run: When running on the ground
  • JumpStart: play once when jumping, then play JumpLoop
  • JumpLoop: play while in the air
  • JumpEnd: play once when landing, then back to Idle
    Idle:站立狀態時
    Run:跑步狀態時
    JumpStart:跳躍時運行一次,,之後進入JumpLoop
    JumpLoop:跳躍懸空狀態
    JumpEnd:着地時運行詞義,之後進入Idle

We'll use a state machine to set up these animation states and their transitions. But first, thinking about how to drive this state machine, we are going to need 2 pieces of data - whether the pawn is walking (versus standing still), and whether the pawn is airborne (versus on the ground). Let's add 2 variables to the Blueprint to store this information. For an overview of variable creation, see the Blueprint Variables documentation.
我們使用狀態機來設置這些動畫狀態和轉換。但首先需要考慮如何驅動狀態機。我們需要2個數據塊 ——無論pawn行走與否,懸空與否。讓我們爲藍圖添加2個變量來存儲這些信息。關於創建變量的概述,請參考 Blueprint Variables文檔。

1. In the My Blueprint tab, click on the New Variable button.
My Blueprint選項卡,點擊New Variable按鍵。

2. Make the variable a Boolean called IsRunning.
創建一個Boolean類型的IsRunning變量。

3. Click on the New Variable button again and add a boolean called IsFalling.
點擊 New Variable按鍵便添加類型爲boolean的IsFalling變量。



New anim vars fps tutorial.png


--------------------------------------------------------------------------------------------------------------

EventGraph —— 事件圖

To set these variables properly while the game is running, we'll edit the Event Graph.
爲了在遊戲運行時正確設置這些變量,我們需要編輯Event Graph。

1. Open the EventGraph by double-clicking on EventGraph in the My Blueprint tab.
My Blueprint選項卡中雙擊打開EventGraph

2. Right-click in the graph to bring up the context menu.
右鍵點出文本菜單

3. Type Update in the context menu search, then click on Event Blueprint Update Animation to add that node.
輸入Update搜索,點擊來添加Event Blueprint Update Animation節點。

Event kismet update animation fps tutorial.png


The Event Blueprint Update Animation node will allow us to update our state variables every time the Animation updates, so they are always in sync with the game state.
Event Blueprint Update Animation節點允許我們在每次動畫更新的時候更新我們的狀態變量,因此他們總是與遊戲狀態同步。

Event kismet node fps tutorial.png


We can find the proper values for our variables by querying the character's CharacterMovementComponent. To get this, we must first get a reference to the animation's owning Character.
我們可以通過請求角色的CharacterMovementComponent來獲取合適的值。爲此,首先我們需要關聯動畫自己的Character。

1. Right-click in the graph to bring up the context menu.
右鍵點開Content menu.

2. Type Owner in the context menu search, then click on Try Get Pawn Owner to add that node.
搜索選擇Try Get Pawn Owner並添加該節點。

3. Drag off the output pin and select Cast to Character from the context menu.
添加Cast to Character節點。

Cast to character fps tutorial.png


4. Wire the output execution pin on Event Blueprint Update Animation to the input execution pin on Cast to Character.
如圖連連看。

Event to cast fps tutorial.png


5. Drag off the As Character output pin and select Get Character Movement.
拖拽As Character輸出引腳,選擇Get Character Movement

Get character movement.png


6. Drag off the Character Movement output pin and select Get Movement Mode.
拖拽Character Movement輸出引腳選擇Get Movement Mode

Get movement mode fps tutorial.png


Now we can query the CharacterMovementComponent's MovementMode and set IsFalling to true if we're in the falling state, or false otherwise.
現在我們可以請求CharacterMovementComponent's MovementMode,如果我麼處於下落狀態設置isFalling爲true,否則爲false。


1. Drag off the Movement Mode output pin and select Equal (Enum).
拖出Movement Mode輸出引腳,選擇Equal (Enum).

Equal enum fps tutorial.png


2. Set the dropdown value on the Equal (Enum) node to Falling.
Equal (Enum) 節點中下拉選擇Falling。

Equal falling fps tutorial.png


3. Alt-click on IsFalling in the My Blueprint tab and drag into the graph to create a Set Is Falling node.
IsFalling變量拖入並選擇Set Is Falling。

Set isFalling fps tutorial.png


4.Connect the unlabeled output execution pin of the Cast to Character node to the input execution pin of the Set Is Falling node, and connect the output Boolean data pin of the Equal (Enum) node to the input Boolean data pin of the Set Is Falling node.
如圖連連看。

Complete isfalling fps tutorial.png


Then, to determine if we're running or standing still, we can get the character's velocity and set IsRunning to true if the magnitude is >0, or false otherwise.
然後,通過獲取角色速度以及當magnitude>0時設置IsRunning爲true(<0時,爲false),來決定角色是停是動。

1. Go back to the Cast To Character node and drag off the As Character pin again. This time, select the Get Velocity node.
如圖連連看。

Get velocity fps tutorial.png


2. If the character is not standing still, the length of its velocity vector will be >0. So, drag off the Return Value vector output pin, and select Vector Length to add that node to the graph.
如果角色不是靜止的話,速度向量的模會大於0.那麼,如圖連連看。

Vector length fps tutorial.png


3.Drag off the Return Value float output pin, and select the > (float) node.
如圖連連看。

Greater than float fps tutorial.png


4. Alt-click on IsRunning in the My Blueprint tab and drag into the graph to create a Set Is Running node.
將IsRuning變量拖進來,設爲set節點.

Set isRunning fps tutorial.png


5. Connect the output execution pin of the Set Is Falling node to the input execution pin of the Set Is Running node, and connect the output Boolean pin of the > (float) node to the input Boolean pin of the Set Is Running node.
如圖連連看。

Final set falling fps tutorial.png

--------------------------------------------------------------------------------------------------------------

AnimGraph —— 動畫圖

Now that our variables are being set properly, we can put together our state machine.
既然我們的變量已設置好了,我們可以玩弄我們的狀態機了。

Add State Machine —— 添加狀態機

1. Double-click on AnimGraph in the My Blueprint tab to open it.
My Blueprint選項卡雙擊打開AnimGraph。

2. Right-click the graph and select State Machines >Add New State Machine... in the context menu.
右鍵選擇State Machines >Add New State Machine...

NewStateMachine fps tutorial.png


3. Right-click on New State Machine in the My Blueprint tab, and rename the state machine to Arms State Machine.
My Blueprint選項卡中右鍵New State Machine,重命名爲Arms State Machine。

4. Connect the output execution pin on the Arms State Machine node to the Result input execution pin on the Final Animation Pose node.
如圖連連看。

ArmsStateMachine fps tutorial.png


5. Double-click the Arms State Machine node to open its graph for editing.
雙擊打開Arms State Machine節點進行編輯。

We need to add our 5 states to this graph.
我們需要在圖中添加五個狀態。

Add States —— 添加狀態

1. Right-click in the graph and select Add State... from the context menu.
右鍵選擇Add State... 

Add state fps tutorial.png


2. Name the state Idle.
3. Double click the state to edit it.
4. Right-click in the graph, and search for "Idle" in the context menu. Click on Play FPP_Idle to insert that node.
5. Connect the output execution pin of the Play FPP_Idle node to the Result input execution pin of the Final Animation Posenode
命名爲Idle;
雙擊打開編輯。
右鍵搜索Idle。點擊插入節點;
連接Play FPP_Idle節點的輸出引腳到Final Animation Pose節點Result輸入引腳。

ArmsStateMachine fps tutorial.png


6. Repeat steps 1-5 for each of the other 4 states:
上訴步驟重複對其他四個狀態使用。

  • Run
  • JumpStart
  • JumpEnd
  • JumpLoop

When you are done, the Arms State Machine graph should look like the below image. Each state should contain the appropriate Play node connected to the Final Animation Pose node.
完成後,看起來應該如下圖所示。每個狀態都應該包含有連接Final Animation Pose節點的Play 節點。

States done fps tutorial.png


Now, we will wire up the transitions between our states. Start by dragging a wire from the Entry node to Idle state.
現在,我們將爲各狀態之間建立過渡。從Entry節點到Idle節點連線開始。

Entry to idle fps tutorial.png


Add the Idle to/from Run Transitions —— 添加IIdle與Run之間的過渡

When our character starts moving the state machine should transition from the Idle to the Run state.
當角色開始移動時,狀態機會從Idle過渡到Run狀態。

1. Drag a wire from the Idle state to the Run state to create a transition.
如圖連連看。

Idle to run fps tutorial.png


2. Double click the transition to edit it. Control-click on IsRunning in the My Blueprint tab and drag into the graph to create a Get Is Running node.
雙擊編輯過渡線。將My Blueprint選項卡中的IsRunning拖入並建立Get Is Running節點。

3. Connect the output pin on the Get Is Running node to the input Can Enter Transition pin on the Result node.
如圖連連看。

IdleToRunCanEnterTransition FPSTutorial.PNG


When our character stops moving the state machine should transition from the Run state to the Idle state.
角色停止運動時會從Run過渡到 Idle 

1. Return to the Arms State Machine graph, and drag a wire from the Run state to the Idle state.
如圖連連看。

RunToIdleTransition FPSTutorial.PNG


2. Double click the transition to edit it. Control-click on IsRunning in the My Blueprint tab and drag into the graph to create a Get Is Running node.
雙擊過渡線進行編輯。將My Blueprint選項卡中的IsRunning拖入創建Get Is Running節點。

3. Drag off the output Boolean pin on the Get Is Running node and create a Not Boolean node.
拖出Get Is Running的輸出引腳創建Not Boolean節點。

4. Connect the output pin on the Not Boolean node to the input Can Enter Transition pin on the Result node.
連接Not Boolean節點與Result節點的Can Enter Transition輸入引腳。

Is not running can enter fps tutorial.png


Add the Idle to JumpStart Transition —— 添加Idley到JumpStart的過渡。

1. Return to the Arms State Machine graph, and drag a wire from the Idle state to the JumpStart state.
如圖連連看。

Idle to jumpstart fps tutorial.png


2. Double click the transition to edit it. Control-click on IsFalling in the My Blueprint tab and drag into the graph to create a Get Is Falling node.
雙擊編輯過渡線。拖入IsFalling創建Get Is Falling 節點。

3. Connect the output Boolean pin on the Get Is Falling node to the input Boolean Can Enter Transition pin on the Result node.
如圖連連看。

Is falling can enter fps tutorial.png


Add the Run to JumpStart Transition —— 添加Run到JumpStart的過渡。

1. Return to the Arms State Machine graph, and drag a wire from the Run state to the JumpStart state.
如圖連連看。

Run to jumpstart fps tutorial.png


2. Double click the transition to edit it. Control-click on IsFalling in the My Blueprint tab and drag into the graph to create a Get Is Falling node.
雙擊編輯過渡線。拖入IsFalling創建Get Is Falling 節點。

3. Connect the output Boolean pin on the Get Is Falling node to the input Boolean Can Enter Transition pin on the Result node.
如圖連連看。

Is falling can enter fps tutorial.png


Add the JumpStart to JumpLoop Transition —— 添加JumpSart到JumpLoop的過渡。

1. Return to the Arms State Machine graph, and drag a wire from the JumpStart state to the JumpLoop state.
如圖連連看。

Jumpstart to jumploop fps tutorial.png


2. Double click the transition to edit it. For this transition, we want it to happen when the JumpStart animation is nearly finished. Right-click in the graph, then search for and select the TimeRemaining for 'FPP_JumpStart' node.
雙擊編輯過渡線。此過渡線,我們想要在JumpStart動畫近乎完成的時候打開。右鍵搜索選擇TimeRemaining for 'FPP_JumpStart' 節點。

3. Drag off of the Time Remaining output pin, and add a <= (float) node using the context menu.
拖出Time Remaining的輸出引腳添加<= (float) 節點。

4. Enter 0.1 in the other input field on the <= (float) node, and then wire the Boolean output pin from that node to the Can Enter Transition input pin on the Result node.
設置連線如圖所示。(PS:下圖中的FPP_JumpEnd 應爲FPP_JumpStart

Jumpend time canenter fps tutorial.png


Add the JumpLoop to JumpEnd Transition —— 添加JumpLoop到JumpEnd過渡

1. Return to the Arms State Machine graph, and drag a wire from the JumpLoop state to the JumpEnd state.
如圖連連看。

Jumploop to jumpend fps tutorial.png


2. Double click the transition to edit it. Control-click on IsFalling in the My Blueprint tab and drag into the graph to create a Get Is Falling node.
雙擊編輯過渡線。拖入IsFalling創建Get Is Falling 節點。

3. Drag off the output Boolean pin on the Get Is Falling node and create a Not Boolean node. Connect the output Boolean pin on the Not Boolean node to the input Boolean Can Enter Transition pin on the Result node.
拖出Get Is Running的輸出引腳創建Not Boolean節點與

JumpLoopToJumpEndCanEnterTransition FPSTutorial.PNG


Add the JumpEnd to Idle Transition —— 添JumpEnd到IIdle的過渡。

1. Return to the Arms State Machine graph, and drag a wire from the JumpEnd state to the Idle state.
如圖連連看。

Jumpend to idle fps tutorial.png


2. Double click the transition to edit it. For this transition, we want it to happen when the JumpEnd animation is nearly finished. Right-click in the graph, then search for and select the TimeRemaining for 'FPP_JumpEnd' node.
雙擊編輯過渡線。此過渡線,我們想要在JumpEnd動畫近乎完成的時候打開。右鍵搜索選擇TimeRemaining for 'FPP_JumpEnd' 節點。

3. Drag off of the Time Remaining output pin, and add a <= (float) node using the context menu.
拖出Time Remaining的輸出引腳添加<= (float) 節點。

4. Enter 0.1 in the other input field on the <= (float) node, and then wire the Boolean output pin from that node to the Can Enter Transition input pin on the Result node.
設置連線如圖所示。

Jumpend time canenter fps tutorial.png


Associate the Animation Blueprint with the Character Blueprint —— 關聯Animation Buleprint到Character到Blueprint

1. Compile and save the Arms_AnimBP Animation Blueprint, then close it.
編譯保存動畫Arms_AnimBP藍圖,關閉。

2. Navigate to the Blueprints folder in the Content Browser, then open the BP_FPSCharacter Blueprint.
打開BP_FPSCharacter藍圖。

3. In Defaults mode, find the Animation section, and then the FirstPersonMesh subsection. Set the AnimationBlueprint for theFirstPersonMesh to the Arms_AnimBP Animation Blueprint we just made.
Defaults模式,找到 Animation 部分,然後找到FirstPersonMesh。爲FirstPersonMesh設置AnimationBlueprintArms_AnimBP

4. Also in Defaults mode, change the FirstPersonMesh transform to {0,0,-150} for translation and {0,0,0} for rotation.
改變FirstPersonMesh的位置信息,其中translation{0,0,-150}rotation {0,0,0} 。

5. Compile and save the Blueprint, then close it.
編譯保存藍圖,關閉。

6. Play your game in the editor. Your arms will be animated, and will transition through their animations as you play. You have completed the FPS tutorial!
Play運行,你的手臂會動起來,並且在你的操作下過渡動畫。你已完成本教程。恭喜你,你已超神。

----------------------------------
4.10 已測試成功,最後的動畫只有手臂輕微上擡,沒有華麗的動作與特效。

--------------------------------------------------------------------------------------------------------------

1、本文爲題主在學習中翻譯,同時在UE4.10.2 版本上嘗試運行,翻譯過程中遇到翻譯不出會暫時留白,翻譯有誤請指出,謝謝!
2、本文在翻譯過程中遇到題主不懂的地方可能會添加題主的知識擴展鏈接。
-------------------------------------------------
在此,再次對博主好友Erin表示感謝。






    /** Gun muzzle's offset from the camera location */
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
    FVector MuzzleOffset;


UCLASS()
class FPSPROJECT_API AFPSGameMode : public AGameMode
{
GENERATED_BODY()
};

virtual void StartPlay() override; // Note that engine version 4.3 changed this method's name to StartPlay(), because of this engine versions before 4.3, or older tutorials, use BeginPlay()

// Note that engine version 4.3 changed the method's name to StartPlay(), because of this engine versions before 4.3, or older tutorials, use BeginPlay()
void AFPSGameMode::StartPlay() 
{
      Super::StartPlay();
 
      StartMatch();
 
      if (GEngine)
      {
            GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("HELLO WORLD"));
      }
}

UCLASS()
class FPSPROJECT_API AFPSGameMode : public AGameMode
{
	GENERATED_BODY()
 
	AFPSGameMode(const FObjectInitializer& ObjectInitializer);  // Our added constructor
 
	virtual void StartPlay() override;
};

#include "FPSCharacter.h"

AFPSGameMode::AFPSGameMode(const class FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

DefaultPawnClass = AFPSCharacter::StaticClass();

AFPSGameMode::AFPSGameMode(const class FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	DefaultPawnClass = AFPSCharacter::StaticClass();
}

發佈了29 篇原創文章 · 獲贊 87 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章