Appearance
虚幻C++基础
CPP项目的目录结构
Cpp项目的目录结构如下:
Binaries*:存放编译生成的结果二进制文件
Config:配置文件
DerivedDataCache*:"DDC",存储引擎针对平台特化后的资源版本。
Intermediate*:"中间文件",存放一些临时生成的文件,例如:
- .obj和预编译头
- VS.vcxproj项目文件
Saved*:存储自动保存文件,其他配置文件,日志文件,引擎崩溃日志,硬件信息,烘焙信息等
Source:代码文件
其中,带星号的都是可以添加进.gitignore的文件夹
编译器里的目录结构
Engine
引擎源码文件,可看不可改
Games
项目工程文件,我们的代码写在这里。
虚幻采用模块的方式进行引擎构建,我们编写的也最终被视为模块。
文件名.Target.cs是模块的配置文件
Visualizers
VS编辑器配置文件
删除C++文件
1、关闭引擎
2、删除想删除的内容
3、删除Binaries文件夹
4、编译 项目.uproject 文件
类命名规则
(虚幻放弃了多继承结构,所以从某个类开始总能向上溯源到一个根本类)
派生自 UObject 的类带有U前缀,如UComponent
派生自 AActor 的类带有A前缀,如AController
模板类,即Template,其前缀是T。如TArray,TMap,TSet
枚举类,即Enums, 其前缀是E
接口类,即Interface, 其前缀通常是I
布尔值以小写b开头,如 bPendingDestruction
派生自SWidget的类(Slate UI)带有前缀S,如SButton
其他类的前缀为字母F,如FVector
typedef的以原型名前缀为准,如typedef TArray FArrayOfMyTypes;
文件名前缀
类型 | 前缀 | 说明 |
---|---|---|
Level/Map | L_ | 关卡 |
Blueprint | BP_ | 常规蓝图 |
Material | M_ | 材质 |
StaticMesh | S_ | 静态网格 |
Skeletal Mesh | SK_ | 骨架网格 |
Texture | T_ | 纹理 |
Particle System | PS_ | 粒子系统 |
Widget Blueprint | WBP_ | 组件蓝图 |
项目目录结构参考
|-- 项目名称
|-- Maps
|-- Textures
|-- Materials
|-- Blueprints
|-- Effects
|-- Animations
|-- Sounds
|-- Sources
命名的参考网址:
https://github.com/uejoy/ue4-style-guide
类导入位置
.cpp文件要在默认导入文件之后添加新的导入
.h文件要在默认导入文件之前添加新的导入
简记为:头前屁屁后
使用代码瞬移、移动、旋转、缩放物体
cpp
// 布尔变量要b开头,引擎编译时会自动去掉
bool bGotoInitLocation;
GetActorLocation();
SetActorLocation(FVector(0.f));
宏属性
cpp
UCLASS(Blueprintable) // Blueprintable
UPROPERTY(BlueprintReadWrite,Category="MyFloat",meta=(ClampMin=-5.0f,ClampMax=5.0f,UIMin=-5.0f,UIMax=5.0f)) // BlueprintReadWrite 蓝图中可读写,category 分类,meta用于限制变量数值
UFUNCTION(BlueprintCallable, Category="MyFunc") // BlueprintCallable 蓝图中可调用,
VisibleAnywhere // 一般用于组件,意味着属性到处可见
EditAnywhere // 同用于组件,意味着属性到处可编辑
EditInstanceOnly // 仅实例可编辑
VisiableInstanceOnly // 仅实例可见
EditDefaultsOnly // 仅默认可编辑
VisibleDefaultsOnly // 仅默认可见
输出日志
可以使用下面这句在日志中输出 Hello
cpp
UE_LOG(LogTemp, Log, TEXT("Hello"));
UE_LOG(LogTemp, Warning, TEXT("X: %f,Y: %f,Z: %f"), hitResult.Location.X, hitResult.Location.Y,hitResult.Location.Z);
注册指令
cpp
// 以下代码在.h文件的类中书写
UFUNCTION(Exec) // Exec意味着将下面的函数注册成为操作指令
void 函数名称(参数);
添加力和力矩
力作用于移动,力矩作用于旋转
cpp
// .cpp
InitForce = FVector(0.f);
InitTorque = FVector(0.f);
bAccelChange = false;
// ::BeginPlay()
MyStaticMesh->Addforce(InitForce, "NAME_None", bAccelChange);
MyStaticMesh->Addforce(InitTorque, "NAME_None", bAccelChange);
输出碰撞信息
cpp
// .cpp
FHitResult hitResult;
AddActorLocalOffset(TickLocationOffset, true, &hitResult);
Pawn类
cpp
// 下面这句的变量不用在.h文件中声明,系统能够自动识别
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
// 下面这句和Actor中的一样
MyStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MyStaticMesh"));
// 组件附加
MyStaticMesh->SetupAttachment(GetRootComponent());
// 这三句的作用是:创建根组件,创建staticmesh组件,然后将staticmesh附加到根组件上
绑定相机及设置玩家
cpp
// 需要导入 Camera/CameraComponent.h 这个头文件
MyCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("MyCamera"));
MyCamera->SetupAttachment(GetRootComponent());
// 设置位置
MyCamera->SetRelativeLocation(FVector(-300.f, 0.f, 300.f));
// 设置旋转
MyCamera->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
// 自动设置玩家为Player0
AutoPossessPlayer = EAutoReceiveInput::Player0;
设置摄像机摇臂
cpp
// 设置摇臂
MySpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("MySpringArm"));
MySpringArm->SetupAttachment(GetStaticMeshComponent());
MySpringArm->AddRelativeRotation(FRotator(-45.f, 0.f, 0.f));
MySpringArm->TargetArmLength = 400.f;
MySpringArm->bEnableCameraLag = true;
MySpringArm->CameraLagSpeed = 3.f;
// 创建相机,绑定相机
MyCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("MyCamera"));
MyCamera->SetupAttachment(GetSpringArmComponent());
"简易包装"
如果代码一行就可以写完,可以在头文件中将声明和定义同时写出
cpp
FORCEINLINE UStaticMeshComponent* GetStaticMeshComponent() {return MyStaticMesh;}
// 其中,FORCEINLINE就代表后面的一行是声明加定义
控制移动和旋转
cpp
// 在头文件中声明私有变量
void MoveForward(float Value);
void MoveRight(float Value);
FVector Velocity;
void LookUp(float Value);
void Turn(float Value);
FVector2D MouseInput;
// 在 .cpp 中创建方法
void AMyPawn::MoveForward(float Value)
{
Velocity.X = FMath::Clamp(Value, -1.0f,1.0f) * maxSpeed;
}
void AMyPawn::MoveRight(float Value)
{
Velocity.Y = FMath::Clamp(Value, -1.0f, 1.0f) * maxSpeed;
}
void AMyPawn::LookUp(float Value)
{
MouseInput.Y = FMath::Clamp(Value, -1.0f, 1.0f);
}
void AMyPawn::Turn(float Value)
{
MouseInput.X = FMath::Clamp(Value, -1.0f, 1.0f);
}
// 构造函数中更改变量
bUseControllerRotationYaw = true;
// 在Tick中添加如下代码
AddControllerYawInput(MouseInput.X);
// XYZ
// Row,Pitch,Yaw
FRotator NewSpringArmRotation = MySpringArm->GetComponentRotation();
NewSpringArmRotation.Pitch = FMath::Clamp(NewSpringArmRotation.Pitch += MouseInput.Y, -80.0f, 0.0f);
MySpringArm->SetWorldRotation(NewSpringArmRotation);
// 在 SetupPlayerInputComponent 函数中添加如下代码:
PlayerInputComponent->BindAxis(TEXT("MoveForward"), this, &AMyPawn::MoveForward);
PlayerInputComponent->BindAxis(TEXT("MoveRight"), this, &AMyPawn::MoveRight);
PlayerInputComponent->BindAxis(TEXT("LookUp"), this, &AMyPawn::LookUp);
PlayerInputComponent->BindAxis(TEXT("Turn"), this, &AMyPawn::Turn);
枚举类型与自定义游戏状态
cpp
// 控制状态的枚举,可以写在gamemodebase.h(游戏模式的头文件)中
UENUM(BlueprintType)
enum class EGameState : uint8
{
EMenu,
EPlay,
EPause,
Ewin,
EGameOver
}