0%

UE客户端开发demo

UE5源码安装、Android打包、Demo展示

UE5源码安装、Android打包

1. 源码安装

UE5的源码安装需要相当大的空间,需要预留足够大的内存(约200-300G)。

Epic所提供的Unreal代码仓库是私有库,需要加入Epic仓库才能拉取源代码。按照官网提示流程(GitHub上的虚幻引擎 - Unreal Engine)操作即可。如果使用git拉取代码失败,可以下载zip包然后解压。

进入UE5的下载目录,双击运行Setup.bat文件,下载第三方库等其他内容。

双击运行GenerateProjectFiles.bat文件生成VS工程文件。对于UE5和VS的版本匹配,可以查看为虚幻引擎C++项目设置Visual Studio开发环境 | 虚幻引擎5.3文档 (unrealengine.com)。推荐使用VS2022。

接下来进行编译:

在Visual Studio中将解决方案配置设置为“Development Editor”模式。

将解决方案平台设置为 Win64。

在“解决方案资源管理器”中找到UE5,点击右键并将其设置为启动项。

在“解决方案资源管理器”中找到UE5,点击右键并将“Build”。

等待编译完成……

编译完成后,启用调试,即可使用UE5。

2. Android打包

UE5和Anroid Studio之间的版本匹配问题见虚幻引擎Android开发要求 | 虚幻引擎5.3文档 (unrealengine.com)。上述网站显示,UE5.3的匹配版本是Flamigo 2022.2.1 Patch 2 May 24, 2023。实测Giraffe也可以打包成功。

打包这一步按照官网流程即可:Android Support for Unreal Engine | 虚幻引擎5.3文档。但是有几个问题需要注意:

问题一:Android SDK Command-line Tools (latest)

官网教程提示安装最新(lastest)版本,而SetupAndroid.bat文件中的最新版本实际上指的是8.0版本。但是Android SDK Command-line Tools的最新版本早已不是8.0版本。因此这一步需要安装8.0版本,并修改SetupAndroid.bat文件中的set SDKMANAGER中的lastest为8.0版本;

问题二:Android Studio下载时,一般为了节省C盘空间,会将其安装到其他盘,这时需要修改SetupAndroid.bat文件

将SetupAndroid.bat文件中set ANDROID_LOCAL修改为实际安装位置

问题三:打包时gradle下载失败

这一般是由于连接外网的问题。可以手动下载对应版本的gradle压缩包,将其放置到下载位置(一般是C盘下),然后重新运行。

角色控制

在C++ Classes文件夹中,右键单击New C++ Classes。选择Character作为基类,将类命名为ASTUBaseCharacter。

新生成的类包含了一些基础的头文件和成员函数。

  • 头文件
    • "CoreMinimal.h":包含了FString、FName等一些常见的类。
    • "GameFramework/Character.h":Character基类。
    • "STUBaseCharacter.generated.h":引入反射系统,为反射提供一些功能,例如我们下面会看到的一些宏:UCLASS()、UPROPERTY等。该头文件需要放在最后一行。
  • 成员函数
    • virtual void BeginPlay():类开始的时调用的函数;
    • virtual void Tick(float DeltaTime) :每一帧调用的函数;
    • virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) :设置输入与事件的绑定。

主要包含两个部分,一是摄像机的设置,二是人物运动。

1. 摄像机设置

在头文件中声明摄像机组件和弹簧臂组件,在.cpp文件中创建摄像机和弹簧臂,并将摄像机附到弹簧臂组件上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// .h
UPROPERTY(VisibleAnyWhere, BlueprintReadWrite, Category = "Components")
USpringArmComponent* SpringArmComponent;

UPROPERTY(VisibleAnyWhere, BlueprintReadWrite, Category = "Components")
UCameraComponent* CameraComponent;

// .cpp

#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"

// 构造函数中
SpringArmComponent = CreateDefaultSubobject<USpringArmComponent>("SpringArmComponent");
SpringArmComponent->SetupAttachment(GetRootComponent());
SpringArmComponent->bUsePawnControlRotation = true;

CameraComponent = CreateDefaultSubobject<UCameraComponent>("CameraComponent");
CameraComponent->SetupAttachment(SpringArmComponent);

弹簧臂在第三人称的视角中,是为了防止转动摄像机时,如果发生了摄像机的位置与物体发生了物理碰撞,避免摄像机进入物体内部,二是自动缩小摄像机与角色之间的距离。

2. 人物运动

人物的前后左右移动需要绑定输入,需要在UE的“编辑”->“项目设置”->“引擎”->“输入”中添加”轴映射“。

轴映射会不断被轮询,从而实现无缝的移动过渡和流畅的游戏行为,例如长按W键人物可以一直前进。而对应的操作映射则是处理离散事件的输入,例如点击空格键,人物跳跃一次。

绑定按钮与对应事件:

1
2
3
4
5
6
7
8
9
10
11
// Called to bind functionality to input
void ASTUBaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);

// ASTUBaseCharacter::MoveForward等这四个是成员函数,实现前后移动和转向
PlayerInputComponent->BindAxis("MoveForward", this, &ASTUBaseCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &ASTUBaseCharacter::MoveRight);
PlayerInputComponent->BindAxis("LookUp", this, &ASTUBaseCharacter::LookUp);
PlayerInputComponent->BindAxis("TurnAround", this, &ASTUBaseCharacter::TurnAround);
}

设置对应事件函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void ASTUBaseCharacter::MoveForward(float Amount)
{
IsMovingForward = Amount > 0.0f;
if (Amount == 0.0f) return;
AddMovementInput(GetActorForwardVector(), Amount);
}

void ASTUBaseCharacter::MoveRight(float Amount)
{
if (Amount == 0.0f) return;
AddMovementInput(GetActorRightVector(), Amount);
}

void ASTUBaseCharacter::LookUp(float Amount)
{
AddControllerPitchInput(Amount);
}

void ASTUBaseCharacter::TurnAround(float Amount)
{
AddControllerYawInput(Amount);
}

AddMovementInput实际上就是通过修改人物的坐标实现的人物移动。

为了能够实现连续的任务左右转向,使用混合空间对人物从启动到左右转向进行了设置。涉及到四个动画和两个参数(Velocity、Direction)。

Direction的计算稍有复杂,为了实现左右转向首先要获得人物的前向位置(ForwardDirection)以及人物运动方向(VelocityDiection)。

借助向量的点乘,可以计算出二者之间的夹角的cos值。左右移动分别设置为正负,可以通过ForwardDirection与VelocityDiection的叉乘计算得到。总体思想为:左右移动根据正负号判断;人物移动方向则根据角度大小来判断,小于90°向前,大于90°向后。

1
2
3
4
5
6
7
8
9
float ASTUBaseCharacter::GetMovementDirection() const
{
if (GetVelocity().IsZero()) return 0.0f;
const auto VelocityNormal = GetVelocity().GetSafeNormal();
const auto AngleBetween = FMath::Acos(FVector::DotProduct(GetActorForwardVector(), VelocityNormal));
const auto CrossProduct = FVector::CrossProduct(GetActorForwardVector(), VelocityNormal);
const auto Degrees = FMath::RadiansToDegrees(AngleBetween);
return CrossProduct.IsZero() ? Degrees : Degrees * FMath::Sign(CrossProduct.Z);
}