張玉婷
(南京傳媒學院傳媒技術學院,南京 210000)
Unreal Engine 5 虛幻引擎(UE5)廣泛應用在游戲、影視、建筑、汽車與運輸等行業中。將UE5 和Visual Studio(VS)結合,可以方便快捷地編寫代碼、編譯程序,設計開發出諸如動作、冒險、解密、RPG 等多種類型的電子游戲[1]。本文介紹一款第一人稱射擊類游戲(FPS)的開發思路。玩家在第一人稱視角下,通過鼠標鍵盤操作,游戲中的角色手持武器射出發射物,擊倒目標物體。
游戲開發的流程是首先在UE5 中新建項目,為項目添加C++代碼。通過創建第一人稱角色的動作軸映射,實現角色移動、旋轉、抬頭、低頭和跳躍的動作。再為角色創建藍圖動畫,添加動畫狀態機。通過在VS 中編寫代碼,實現用鼠標對攝像機的控制和游戲指令輸入[2]。最后導入發射物網格體,設置發射物的碰撞和生命周期,再添加代碼實現對目標的射擊。
啟動UE5 虛幻引擎新建游戲項目,選擇Blank template,項目類型改為C++,確定選擇No Starter Content。在Content Browser 的Content的空白處單擊鼠標右鍵,創建新文件夾,用來存放游戲相關的文件,命名為MyGame。在Edit菜單中打開Project Settings,在左側選項卡的Project 中點擊Maps & Modes,在Editor Startup Map 下拉菜單下選擇MyGame,保存并退出設置。接著在Tools 菜單中選擇Open Visual Studio打開C++代碼。項目啟動之后,在Solution Explorer里會看到.cpp 和.h 文件,編寫的代碼將存放在這些文件中。
本游戲使用C++類向導將需要創建的角色類添加到項目中。在UE5 引擎界面的Tools 菜單中選擇New C++ Class...,創建新的父類。在Choose Parent Class 中選擇Character,新的類命名為MyCharacter,點擊Create Class。在VS 的Solution Explorer 中,依次打開MyProject 里面的Source的FPSProject。在VS中添加如下代碼:
Void AFPSCharacter::SetupPlayerInputComponent(UInputComponent*PlayerInputComponent)
Super::SetupPlayerInputComponent(PlayerInputComponent);
鼠標右鍵點擊MyProject,選擇Build 編譯項目。再返回虛幻編輯器,新編譯的MyCharacter類在Content Browser中就創建完成了。
FPS游戲需要兩個分開的網格體代替玩家角色。其中一個全身網格體作為玩家軀體,用于從第三人稱視角觀察角色。當玩家以第一人稱視角進行游戲時,全身網格體是隱藏的。通過設置軸映射、執行代碼,實現角色前后左右移動和跳躍的動作。
由于角色類已創建了SkeletalMeshComponent 對象,因此只需要導入已有的SkeletalMesh資產。鼠標右鍵單擊Content 的空白處,打開Import Asset 對話框。點擊Import to 中的Game...,打開Import。選擇已創建好的MyPeople.fbx 骨骼網格體文件,點擊Open,在FBX Import Options對話框中依次點擊Import All 和Save,將網格體添加到項目中。
在Content的Blueprints中,雙擊BP_MyCharacter藍圖類,在藍圖編輯器的Components 選項卡中點擊Mesh 組件。在右側的Details 選項卡的Mesh 里Skeletal Mesh 行的下拉列表中選擇無,然后選擇MyPeople 骨骼網格體。在Details 的Transform 中將變換的Z軸向位置設置為-70,使SkeletalMeshComponent與CapsuleComponent對齊。
除了全身網格體,第一人稱射擊類游戲還需要有代表武器和手部的網格體。這個網格體通常附著到攝像機,并且僅當玩家以第一人稱視角查看游戲時才對玩家可見。
右鍵點擊內容瀏覽器的文件框,打開Import Asset對話框。點擊Import to的Game...,在Import對話框中找到并選擇MyArm.fbx網格體文件,點擊Open 將網格體導入到項目中。在FBX Import Options 對話框中將Skeleton 設置為None,然后點擊Import All。
打開BP_MyCharacter 藍圖編輯器,在Components 選項卡中找到FPSMesh 組件。在Details選項卡的Mesh條目中點擊顯示為None的下拉菜單,選擇MyArm 骨骼網格體,將手臂添加到Viewport。接著創建網格體組件,并附加到FPS攝像機,變換屬性設置為在攝像機前面,Location設置為220,0,35,Rotation設置為180,50,180。在VS中添加如下代碼:
FPSMesh=CreateDefaultSubobject<USkeletalMesh-Component>(TEXT(“FirstPersonMesh”));
check(FPSMesh!=nullptr);
FPSMesh->SetupAttachment(FPSCameraComponent);
軸映射是將鍵盤、鼠標和控制器的輸入映射到游戲中,綁定到游戲角色的某個動作上。軸映射中常見的就是通過輸入WASD 鍵或箭頭鍵,控制角色自由地向前后左右移動,觸發游戲行為。在UE5 中打開項目,在Edit 菜單中點擊Project Settings,在選項卡左側的Engine 標題欄下點擊Input。在Bindings 中點擊Axis Mappings 旁邊的+號,點擊Axis Mappings 左側的箭頭,在文本框中輸入MoveForward,然后點擊左側箭頭,在下拉菜單中選擇W。點擊MoveForward 旁邊的+號,在第二個下拉菜單中從Keyboard 下拉列表中選擇S,在S 旁邊的Scale 字段中輸入-1。
在典型的第一人稱游戲控制模式中,角色的移動是相對于攝像機的。因此需要使用PlayerController 獲取角色的控制旋轉輸入值。MoveForward 函數將忽略控制旋轉輸入值的Pitch分量,將輸入限制在XY 平面上,以確保在向上或向下看時,角色將沿著地面移動。在VS 中添加如下代碼:
PlayerInputComponent->BindAxis(“MoveForward”,this,&AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis(“MoveRight”,this,&AFPSCharacter::MoveRight);
在此步驟中,為角色添加能夠環顧四周并用鼠標操縱的功能。在Bindings 中,點擊Axis Mappings 旁邊的+號,點擊Axis Mappings 左側的箭頭。在文本框中輸入Turn,然后點擊左側的箭頭,從Mouse 下拉列表中選擇Mouse X。輸入scale 的值為1.0,完成轉頭的軸映射。用同樣的方法,在文本輸入框中輸入LookUp,從Mouse下拉列表中選擇Mouse Y,完成抬頭低頭的軸映射。
接著將攝像機組件附加到膠囊體組件,編寫代碼將攝像機的位置調整為略高于角色眼睛的位置,同時允許pawn 控制攝像機的旋轉。在VS中添加如下代碼:
FPSCameraComponent->SetupAttachment(Cast-Checked<USceneComponent,UCapsuleComponent>(GetCapsuleComponent()));
FPSCameraComponent->SetRelativeLocation(FVector(0.0f,0.0f,50.0f+BaseEyeHeight));
FPSCameraComponent->bUsePawnControlRotation=true;
設置完角色后,需要給游戲添加武器和發射物。首先添加射擊動作映射,在Edit菜單中點擊Project Settings。在Engine 標題欄下選擇Input 中的Bindings,點擊Action Mappings 旁邊的+號。在文本輸入框中輸入Fire,從Mouse 下拉列表中選擇Left Mouse Button。接著添加發射物類,在File 菜單中選擇New C++Class...,以選擇新的父類。再打開Choose Parent Class 菜單,向下選擇Actor 作為父類,然后點擊Next,將新類命名為“MyProjectile”,然后點擊Create Class。
接著添加發射物移動組件,設置發射物的初始速度和碰撞半徑,綁定發射輸入操作,定義發射物的生成位置。初始化射擊方向上發射物速度的函數,以及槍口相對于攝像機位置的偏移。在VS中添加如下代碼:
UPROPERTY(VisibleDefaultsOnly,Category=Projectile)
USphereComponent*CollisionComponent;
CollisionComponent=CreateDefaultSubobject<USphere-Component>(TEXT(“SphereComponent”));
CollisionComponent->InitSphereRadius(15.0f);
void AFPSProjectile::FireInDirection(const FVector&ShootDirection)
ProjectileMovementComponent->Velocity=Shoot-Direction*ProjectileMovementComponent->Initial-Speed;
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=Gameplay)
FVector MuzzleOffset;
首先創建一個球狀的網格體作為發射物,鼠標右鍵單擊Content Browser空白處,打開Import Asset 對話框,點擊Import to 下的Game...,找到并選擇Bool.fbx網格體文件,點擊Open,在彈出的對話框中點擊Import All,將網格體添加到項目中。導入的網格體可以根據需要設置適合的材質和縮放大小。通過代碼實現在槍口位置生成發射物,射擊方向略向上傾斜,設置發射物的初始軌跡。在VS中添加如下代碼:
FRotator MuzzleRotation=CameraRotation;
MuzzleRotation.Pitch+=10.0f;
UWorld*World=GetWorld();
if(World)
FActorSpawnParameters SpawnParams;
SpawnParams.Owner=this;
SpawnParams.Instigator=GetInstigator();
AFPSProjectile*Projectile=World->SpawnActor<AFPSProjectile>(ProjectileClass,MuzzleLocation,MuzzleRotation,SpawnParams);
if(Projectile)
FVector LaunchDirection=MuzzleRotation.Vector();
Projectile->FireInDirection(LaunchDirection);
本游戲中,發射物在發出后與其他對象碰撞并銷毀,輸入InitialLifeSpan=3.0f,每個生成的發射物會在三秒后從場景中消失。
在Object Channels 中選擇New Object Channel...,創建新碰撞通道。將新碰撞通道命名為“Projectile”,確 保將Default Response 設 置 為Block, 然 后 點 擊Accept。 在Preset 中 選 擇New...,將新配置文件命名為“Projectile”,并設置碰撞預設,設定發射物與Pawn重疊。
游戲中需要為角色添加一些動畫。在Content Browser中單擊鼠標右鍵,選擇Import to,在Game 的Animations 中導入角色動畫。在彈出的對話框中選擇Select Skeleton 標題下的My-Arm_Skeleton,然后點擊Import All導入所有動畫。
接著創建動畫藍圖,在Content 中單擊鼠標右鍵,在Create Advanced Asset 里展開Animation并選擇Animation Blueprint。選擇AnimInstance作為父類,并選擇MyArm_Skeleton 作為目標骨架。雙擊新動畫藍圖打開Blueprint Editor,在My Blueprint 選項卡中點擊Add New 按鈕,并選擇Variable。
將該變量設置為Boolean,并將其命名為“IsRunning”。在My Blueprint 選項卡中,點擊Add New 按鈕并選擇Variable。將該變量設置為Boolean,并將其命名為“IsFalling”。由此添加狀態機過渡變量。
接著編輯動畫的事件圖表,使動畫過渡變量在游戲運行時能夠正確觸發。打開Arms_AnimBP,雙擊My Blueprint 選項卡中的EventGraph,打開事件圖表。在圖表中點擊右鍵,彈出Context Menu。在Context Menu 的搜索字段中輸入“Update”,然后點擊Event Blueprint Update Animation 以添加該節點。Event Blueprint Update Animation 節點用于在每次更新動畫時更新狀態變量,使變量始終與游戲狀態同步。在圖表中點擊右鍵,彈出Context Menu。在Context Menu 的搜索字段中輸入“Owner”,然后點擊Try Get Pawn Owner 以添加該節點。從輸出引腳連出引線,并在Context Menu 中選擇Cast to Character。將Event Blueprint Update Animation 節點上的輸出執行引腳關聯到Cast to Character 節點上的輸入執行引腳。從As Character 輸出引腳連出引線,并選擇Get Character Movement。從Character Movement 輸出引腳連出引線,并選擇Get Movement Mode。從Movement Mode 輸出引腳連出 引 線, 并 選 擇Equal(Enum)。 將Equal(Enum)節點上的下拉菜單值設置為Falling。按住Alt 鍵的同時點擊My Blueprint 選項卡中的IsFalling,將其拖到圖表中,創建一個Set Is Falling 節點。將Cast to Character 節點的未標記輸出執行引腳連接到Set Is Falling 節點的輸入執行引腳,并將Equal(Enum)節點的輸出布爾數據引腳連接到Set Is Falling 節點的輸入布爾數據引腳。返回Cast To Character 節點,并從As Character 引腳再次連出引線。這次選擇Get Velocity 節點。如果角色不是站立不動,其速度向量的長度將大于零。因此,從Return Value 向量輸出引腳連出引線,并選擇Vector Length 以將該節點添加到圖表。從Return Value 浮點輸出引腳連出引線,并選擇>(float)節點。按住Alt鍵的同時點擊My Blueprint選項卡中的IsRunning,將其拖到圖表中,創建一個Set Is Running 節點。將Set Is Falling 節點的輸出執行引腳連接到Set Is Running節點的輸入執行引腳,并將>(float)節點的輸出布爾引腳連接到Set Is Running 節點的輸入布爾引腳。
本文提供了一個第一人稱射擊類游戲開發的簡單創作思路。在實際開發過程中,一款可發售的游戲還需要有地編、特效、動畫、交互等多方面的設計和制作。而游戲的趣味性、難易度和競技性也是開發人員在設計過程中必須思考的問題。更多的創意設計和文化元素,適當的獎勵機制和游戲反饋,都可以給玩家帶去更好的游戲體驗,提升游戲的品質[3]。