根据UE4官方文档,自己动手创建一个第一人称射击游戏。文档详细地址:UE4官方文档第一人称射击游戏
- 定义角色
FPSCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "FPSCharacter.generated.h"
UCLASS()
class FPSPROJECT_API AFPSCharacter : public ACharacter {
GENERATED_BODY()
public:
// Sets default values for this character's properties
AFPSCharacter();
//枪口的偏移位置
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AAA")
FVector MuzzleOffset;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
private:
//向前或者向后移动
UFUNCTION()
void MoveForward(float Value);
//向左或者向右移动
UFUNCTION()
void MoveRight(float Value);
UFUNCTION()
void StartJump();
UFUNCTION()
void StopJump();
UFUNCTION()
void Fire();
//摄像机组件
/**
* 如果不添加摄像机组件的话,会有一个默认的摄像机组件,并且在模型脖子的位置
*/
UPROPERTY(VisibleAnywhere, Category = "AAA")
class UCameraComponent* FPSCameraComponent;
//设置第一人称的网格体组件
UPROPERTY(VisibleAnywhere, Category = "AAA")
class USkeletalMeshComponent* FPSMesh;
//生产发射物类
/**
* TSubclassOf 是提供的UClass类型安全模板类
*/
UPROPERTY(EditDefaultsOnly, Category = "AAA")
TSubclassOf<class AFPSProjectile> ProjectileClass;
};
FPSCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "FPSCharacter.h"
#include "Engine/Engine.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/SkeletalMeshComponent.h"
#include "FPSProjectile.h"
// Sets default values
AFPSCharacter::AFPSCharacter() {
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FPSCameraComponent"));
//将摄像机组件放到胶囊体下面
#if 0
FPSCameraComponent->SetupAttachment(GetRootComponent());
#else
FPSCameraComponent->SetupAttachment(Cast<UCapsuleComponent>(GetCapsuleComponent()));
#endif
//将摄像机放到眼睛上方不远处
FPSCameraComponent->SetRelativeLocation(FVector(0.0, 0.0, 50.0 + BaseEyeHeight));
//使用Pawn来控制摄像机旋转
FPSCameraComponent->bUsePawnControlRotation = true;
//设置第一人称骨骼模型
FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
//设置该模型仅对玩家可见
FPSMesh->SetOnlyOwnerSee(true);
//设置根组件
FPSMesh->SetupAttachment(FPSCameraComponent);
//禁用部分环境阴影,保留单一模型存在的假象
FPSMesh->bCastDynamicShadow = false;//动态阴影
FPSMesh->CastShadow = false;//投影
//拥有玩家无法看到普通(第三人称)身体模型
GetMesh()->SetOwnerNoSee(true);
}
// Called when the game starts or when spawned
void AFPSCharacter::BeginPlay() {
Super::BeginPlay();
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
// Called every frame
void AFPSCharacter::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) {
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis(TEXT("MoveRight"), this, &AFPSCharacter::MoveRight);
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
}
void AFPSCharacter::MoveForward(float Value) {
FVector direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
AddMovementInput(direction, Value);
}
void AFPSCharacter::MoveRight(float Value) {
FVector direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
AddMovementInput(direction, Value);
}
void AFPSCharacter::StartJump() {
bPressedJump = true;
}
void AFPSCharacter::StopJump() {
bPressedJump = false;
}
void AFPSCharacter::Fire() {
if (ProjectileClass){
//获取摄像机的视点变换的位置
FVector CameraLocation;
FRotator CameraRotation;
GetActorEyesViewPoint(CameraLocation, CameraRotation);
//枪口的本地坐标装换成世界坐标
FVector MuzzleLoacation = CameraLocation + FTransform(CameraRotation).TransformVector(MuzzleOffset);
FRotator MuzzleRotator = CameraRotation;
//枪口向上抬起10.0度
MuzzleRotator.Pitch += 10.0;
UWorld* world = GetWorld();
if (world){
//生成物参数,也就是生产子弹的参数
FActorSpawnParameters SpawnParameters;
SpawnParameters.Owner = this;
SpawnParameters.Instigator = GetInstigator();
//在枪口出生产发射物
AFPSProjectile* FPSProjectile = world->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLoacation, MuzzleRotator, SpawnParameters);
//设置发射物的初始轨道
FVector LaunchDirection = MuzzleRotator.Vector();
FPSProjectile->FireInDirection(LaunchDirection);
}
}
}
- HUD
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "FPSHUD.generated.h"
/**
*
*/
UCLASS()
class FPSPROJECT_API AFPSHUD : public AHUD {
GENERATED_BODY()
public:
virtual void DrawHUD()override;
UPROPERTY(EditAnywhere)
UTexture2D* CrosshairTexture;
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "FPSHUD.h"
#include "Engine/Canvas.h"
void AFPSHUD::DrawHUD() {
Super::DrawHUD();
if (CrosshairTexture){
//找到画布的中心
FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f);
FVector2D CrossHairDrawPosition(Center.X - (CrosshairTexture->GetSurfaceWidth() * 0.5), Center.Y - (CrosshairTexture->GetSurfaceHeight() * 0.5));
FCanvasTileItem TileItem(CrossHairDrawPosition,CrosshairTexture->Resource, FLinearColor::White);
Canvas->DrawItem(TileItem);
}
}
- 子弹类
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FPSProjectile.generated.h"
/**
* 子弹类
*/
UCLASS()
class FPSPROJECT_API AFPSProjectile : public AActor {
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AFPSProjectile();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
public:
//球体碰撞组件
UPROPERTY(VisibleDefaultsOnly, Category = "AAA")
class USphereComponent* CollisionComponment;
//子弹组件
UPROPERTY(VisibleAnywhere, Category = "AAA")
class UStaticMeshComponent* ProjectileComponent;
UPROPERTY(VisibleAnywhere, Category = "AAA")
class UProjectileMovementComponent* ProjectileMovementComponent;
//在发射方向上设置在发射物的初始速度
void FireInDirection(const FVector& ShootDirection);
};
// Fill out your copyright notice in the Description page of Project Settings.
#include "FPSProjectile.h"
#include "Components/SphereComponent.h"
#include "GameFramework/ProjectileMovementComponent.h"
// Sets default values
AFPSProjectile::AFPSProjectile() {
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
//碰撞球体
CollisionComponment = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
CollisionComponment->SetSphereRadius(15.0);//设置球体半径
RootComponent = Cast<USceneComponent>(CollisionComponment);
//静态网格体
ProjectileComponent = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ProjectileComponent"));
ProjectileComponent->SetupAttachment(RootComponent);
//运动组件
ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent"));
ProjectileMovementComponent->SetUpdatedComponent(CollisionComponment);//设置更新的组件
//设置碰撞预设
CollisionComponment->BodyInstance.SetCollisionProfileName(TEXT("Projectile"));
ProjectileMovementComponent->InitialSpeed = 3000.0;//设置初始速度
ProjectileMovementComponent->MaxSpeed = 3000.0;//设置最大速度
//这个子弹在旋转过程中在每一帧中都要更新,以匹配他的速度方向
ProjectileMovementComponent->bRotationFollowsVelocity = true;
//设置反弹
ProjectileMovementComponent->bShouldBounce = true;
//设置反弹系数
ProjectileMovementComponent->Bounciness = 0.3;
//设置重力系数
ProjectileMovementComponent->ProjectileGravityScale = 0.0;
//3秒后消亡
InitialLifeSpan = 3.0;
}
// Called when the game starts or when spawned
void AFPSProjectile::BeginPlay() {
Super::BeginPlay();
}
// Called every frame
void AFPSProjectile::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
}
void AFPSProjectile::FireInDirection(const FVector& ShootDirection) {
ProjectileMovementComponent->Velocity = ShootDirection * ProjectileMovementComponent->InitialSpeed;
}
- 游戏模式类
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "FPSProjectGameModeBase.generated.h"
/**
*
*/
UCLASS()
class FPSPROJECT_API AFPSProjectGameModeBase : public AGameModeBase
{
GENERATED_BODY()
private:
virtual void StartPlay()override;
};
// Copyright Epic Games, Inc. All Rights Reserved.
#include "FPSProjectGameModeBase.h"
#include "Engine/Engine.h"
#include "Kismet/KismetSystemLibrary.h"
void AFPSProjectGameModeBase::StartPlay() {
Super::StartPlay();
if (GEngine) {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Hello World, this is FPSGameMode!"));
}
UKismetSystemLibrary::DrawDebugCoordinateSystem(GetWorld(), FVector(0.0, 0.0, 50.0), FRotator(0.0, 0.0, 0.0), 10.0, 100,10);
UKismetSystemLibrary::DrawDebugString(GetWorld(), FVector(100.0, 0.0, 100.0), TEXT("My Name"), NULL, FLinearColor::Red, 50.0);
}
- 具体的模型下载可以在官网链接上下载
- UEEditor截图