快速开始: https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/CPPProgrammingQuickStart/
角色和组件: https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/Components/
本文主要根据上面两个链接中的官方教程写一些代码注释和个人理解,感觉这两篇完全搞懂了就可以开始照猫画虎了。
一、快速开始
1、代码注释
FloatingActor.h
// 版权所有 1998-2019 Epic Games, Inc。保留所有权利。
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FloatingActor.generated.h"
UCLASS()
class QUICKSTART_API AFloatingActor : public AActor
{
GENERATED_BODY()
public:
// 设置此Actor属性的默认值
AFloatingActor(); //构造函数
UPROPERTY(VisibleAnywhere) //组件属性设置为可见
UStaticMeshComponent* VisualMesh; //静态网格组件
protected:
// 游戏开始时或生成时调用
virtual void BeginPlay() override; //初始化函数
public:
// 逐帧调用
virtual void Tick(float DeltaTime) override; //滴答函数
};
FloatingActor.cpp
// 版权所有 1998-2019 Epic Games, Inc。保留所有权利。
#include "FloatingActor.h"
// 设置默认值
AFloatingActor::AFloatingActor()
{
// 将此Actor设为逐帧调用Tick()。如无需此功能,可关闭以提高性能。
PrimaryActorTick.bCanEverTick = true; //开启滴答
VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh")); //创建默认参数的子对象,是静态网格体组件
VisualMesh->SetupAttachment(RootComponent); //将用于可视化的静态网格体组件放到根组件下
static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube"));//定义资产,例如材质、贴图等
if (CubeVisualAsset.Succeeded())
{
VisualMesh->SetStaticMesh(CubeVisualAsset.Object); //设置资产
VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f)); //设置位置
}
}
// 游戏开始时或生成时调用
void AFloatingActor::BeginPlay()
{
Super::BeginPlay();
}
// 逐帧调用
void AFloatingActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//1、获得actor位置和角度
FVector NewLocation = GetActorLocation();
FRotator NewRotation = GetActorRotation();
//2、计算角度和高度
float RunningTime = GetGameTimeSinceCreation();
float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
NewLocation.Z += DeltaHeight * 20.0f; //Scale our height by a factor of 20
float DeltaRotation = DeltaTime * 20.0f; //Rotate by 20 degrees per second
NewRotation.Yaw += DeltaRotation;
//3、设置位置和角度
SetActorLocationAndRotation(NewLocation, NewRotation);
}
2、总结
(1)常见函数
CreateDefaultSubobject
资料:
https://blog.csdn.net/luofeixiongsix/article/details/81061764
https://blog.csdn.net/jfengsky/article/details/109274293
模板函数,用于创建组件或者子对象
SetupAttachment
资料:https://blog.csdn.net/jfengsky/article/details/109271706
用于将组件附加到指定组件下,每个actor都有一个根组件,每个组件都可以添加到别的组件或者actor下
(2)命名规则
资料:https://zhuanlan.zhihu.com/p/564438053
(3)常见宏
ue4中的宏往往被用于说明相关对象的性质,比如变量是否可以在面板修改、类是否可以被继承等
UPROPERTY()
官方文档:https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Properties/
用于对变量进行设置,比如是否可以在画面中被观测、在面板中是否可以被修改。
GENERATED_BODY()
跟继承有关的宏,每个类都要有,没咋看懂就不瞎说了。
UCLASS()
资料:https://blog.csdn.net/ttm2d/article/details/106302474
UCLASS()让编译器识别其是uobject的衍生类,并设置相关参数
二、actor和component
1、代码分析
CollidingPawn.h
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "CollidingPawn.generated.h"
UCLASS()
class HOWTO_COMPONENTS_API ACollidingPawn : public APawn
{
GENERATED_BODY()
public:
// 设置此Pawn属性的默认值
ACollidingPawn();
protected:
// 游戏开始或生成时调用
virtual void BeginPlay() override;
public:
// 逐帧调用
virtual void Tick( float DeltaSeconds ) override;
// 调用以将功能与输入绑定
virtual void SetupPlayerInputComponent(class UInputComponent* InInputComponent) override; //这个函数实现类似于中断初始化的操作,只在初始化时候运行。在设置完成后,会在特定事件发生后触发回调函数。
UPROPERTY()
class UParticleSystemComponent* OurParticleSystem; //粒子系统组件
UPROPERTY()
class UCollidingPawnMovementComponent* OurMovementComponent; //自定义移动组件
virtual UPawnMovementComponent* GetMovementComponent() const override;
void MoveForward(float AxisValue);
void MoveRight(float AxisValue);
void Turn(float AxisValue);
void ParticleToggle();
};
CollidingPawn.cpp
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "CollidingPawn.h"
#include "CollidingPawnMovementComponent.h" //自定义移动组件
#include "UObject/ConstructorHelpers.h"
#include "Particles/ParticleSystemComponent.h" //粒子组件
#include "Components/SphereComponent.h" //圆形组件
#include "Camera/CameraComponent.h" //摄像机组件
#include "GameFramework/SpringArmComponent.h" //弹簧臂组件
// 设置默认值
ACollidingPawn::ACollidingPawn()
{
// 设置该Pawn以逐帧调用Tick()。如无需此功能,可关闭以提高性能。
PrimaryActorTick.bCanEverTick = true;
// 根组件将成为对物理反应的球体
USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
RootComponent = SphereComponent; //将根组件改为圆组件
SphereComponent->InitSphereRadius(40.0f); //半径
SphereComponent->SetCollisionProfileName(TEXT("Pawn")); //设置碰撞
// 创建并放置网格体组件,以便查看球体位置
UStaticMeshComponent* SphereVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
SphereVisual->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
if (SphereVisualAsset.Succeeded())
{
SphereVisual->SetStaticMesh(SphereVisualAsset.Object);
SphereVisual->SetRelativeLocation(FVector(0.0f, 0.0f, -40.0f));
SphereVisual->SetWorldScale3D(FVector(0.8f));
}
// 创建可激活或停止的粒子系统
OurParticleSystem = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("MovementParticles"));
OurParticleSystem->SetupAttachment(SphereVisual);
OurParticleSystem->bAutoActivate = false;
OurParticleSystem->SetRelativeLocation(FVector(-20.0f, 0.0f, 20.0f));
static ConstructorHelpers::FObjectFinder<UParticleSystem> ParticleAsset(TEXT("/Game/StarterContent/Particles/P_Fire.P_Fire"));
if (ParticleAsset.Succeeded())
{
OurParticleSystem->SetTemplate(ParticleAsset.Object);
}
// 使用弹簧臂给予摄像机平滑自然的运动感。
USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraAttachmentArm"));
SpringArm->SetupAttachment(RootComponent);
SpringArm->SetRelativeRotation(FRotator(-45.f, 0.f, 0.f));
SpringArm->TargetArmLength = 400.0f;
SpringArm->bEnableCameraLag = true;
SpringArm->CameraLagSpeed = 3.0f;
// 创建摄像机并附加到弹簧臂
UCameraComponent* Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("ActualCamera"));
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
// 控制默认玩家
AutoPossessPlayer = EAutoReceiveInput::Player0;
// 创建移动组件的实例,并要求其更新根组件。
OurMovementComponent = CreateDefaultSubobject<UCollidingPawnMovementComponent>(TEXT("CustomMovementComponent"));
OurMovementComponent->UpdatedComponent = RootComponent;//设置移动时需要更新的组件
}
// 游戏开始或生成时调用
void ACollidingPawn::BeginPlay()
{
Super::BeginPlay();
}
// 逐帧调用
void ACollidingPawn::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
// 调用以将功能与输入绑定
void ACollidingPawn::SetupPlayerInputComponent(class UInputComponent* InInputComponent)
{
Super::SetupPlayerInputComponent(InInputComponent);
InInputComponent->BindAction("ParticleToggle", IE_Pressed, this, &ACollidingPawn::ParticleToggle);//设置事件发生时的回调函数
InInputComponent->BindAxis("MoveForward", this, &ACollidingPawn::MoveForward);
InInputComponent->BindAxis("MoveRight", this, &ACollidingPawn::MoveRight);
InInputComponent->BindAxis("Turn", this, &ACollidingPawn::Turn);
}
UPawnMovementComponent* ACollidingPawn::GetMovementComponent() const
{
return OurMovementComponent;
}
void ACollidingPawn::MoveForward(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorForwardVector() * AxisValue);
}
}
void ACollidingPawn::MoveRight(float AxisValue)
{
if (OurMovementComponent && (OurMovementComponent->UpdatedComponent == RootComponent))
{
OurMovementComponent->AddInputVector(GetActorRightVector() * AxisValue);
}
}
void ACollidingPawn::Turn(float AxisValue)
{
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += AxisValue;
SetActorRotation(NewRotation);
}
void ACollidingPawn::ParticleToggle()
{
if (OurParticleSystem && OurParticleSystem->Template)
{
OurParticleSystem->ToggleActive();
}
}
2、总结
(1)难理解代码汇总
资料:
https://zhuanlan.zhihu.com/p/568444863
https://blog.csdn.net/jfengsky/article/details/109271706
https://blog.csdn.net/WAN_EXE/article/details/78604821
1、OurMovementComponent->UpdatedComponent = RootComponent;
在移动组件接收到要移动的数据后,需要知道对哪一个组件的位置进行修改,这行代码就是用来指出那个被控制组件的。
2、RootComponent = SphereComponent;
RootComponent是从actor基类那里继承来的,直接设置可以修改根组件。
3、InInputComponent->BindAction
用于绑定事件和回调函数
(2)常见类的继承关系
资料:https://blog.csdn.net/YoYuanZhizheng/article/details/123707769
Uobject类、Actor类、Pawn类(继承自actor,增加移动功能)、Character类(继承自Pawn)、Controller类
(3)组件
资料:https://docs.unrealengine.com/4.26/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/UnrealArchitecture/Actors/Components/
组件附着于actor或者其他组件之下,用于实现某一个特定功能,比如移动、粒子、发射等。
Actor组件(类 UActorComponent)最适用于抽象行为,例如移动、物品栏或属性管理,以及其他非物理概念。Actor组件没有变换,即它们在场景中不存在任何物理位置或旋转。
场景组件(类 USceneComponent、UActorComponent 的子项)支持基于位置的行为,这类行为不需要几何表示。这包括弹簧臂、摄像机、物理力和约束(但不包括物理对象),甚至音频。
Primitive组件(类 UPrimitiveComponent、USceneComponent 的子项)是拥有几何表示的场景组件,通常用于渲染视觉元素或与物理对象发生碰撞或重叠。这包括静态或骨架网格体、Sprite或公告板、粒子系统以及盒体、胶囊体和球体碰撞体积。
(4)典型的actor运行方式
ue4中都是以actor为单位的,在actor中以不同的方式运行组件,进而实现各种效果。目前看到的actor能以构造函数、初始化函数、滴答函数、中断回调这四种形式进行操作,很像单片机中的运行方式。文章来源:https://www.toymoban.com/news/detail-488094.html
3、扩展
其他常见组件:https://docs.unrealengine.com/4.27/zh-CN/Basics/Components/
其他基础教程:https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/ProgrammingWithCPP/CPPTutorials/文章来源地址https://www.toymoban.com/news/detail-488094.html
到了这里,关于ue4基础入门(一)actor和component的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!