UE4C++]小知识点

UnrealEngin C++小知识点

删除C++的类

  1. 打开工程目录
  2. Source >工程名文件夹 >删除要删的类
  3. Binaries 文件夹删除
  4. 工程名.uproject 右键Generate Visual Studio Project Files
  5. 工程名.uproject 右键Open
  6. 提示缺失文件是否重新生成,选是

UE4输出日志的方法

  1. 在UE4中蓝图里输出到屏幕里的节点是printfString
  2. 在C++中,使用
  3. 这个方法好处,可以显示出当前打印出是谁调用的,在做网络游戏中很有用
// 要引入头文件
#include "Kismet/KismetSystemLibrary.h"
UkismetSystemLibrary::PrintString(this,TEXT("Hello World!"));
  1. 或使用
GEngin->Add
  1. 如果在Console中输出日志
int num = 10;
UE_LOG(LogTemp,Warning,TEXT("当前值:%d"),num);

其中的LogTemp可以换为自己定义的类型
如下:

//在.h中声明 (别名,默认输出级别,All)
DECLARE_LOG_CATEGORY_EXTERN(LogCustom, Log, All);

//在.cpp中定义
DEFINE_LOG_CATEGORY(LogCppActor);

// 使用
UE_LOG(LogCustom,Warning,TEXT("HelloWorld"));

UE4宏

#if WITH_EDITORONLY_DATA
// 这里面只在编辑器中生效
#endif

C++使用Timer移动Actor

主要方法:

得到需要的起点、终点、时长、速度等,能过每帧计算步长进行移动,然后判断是否结尾而结束计时器。

// TetrisBlock.h
float TotalFallingTime; // 下落总时间
float FallingStartTime; // 下落开始时间
FVector FallingStartLocation; // 下落开始位置
FVector FallingEndLocation; // 下落结束位置
FTimerHandle TickFallingHandle; // 掉落动画计时器
float TileMoveSpeed; // 移动速度
  1. 使用StartFalling()计算移动时的位置与时间,开始计时器
void ATetrisBlock::StartFalling()
{
	FallingStartTime = GetWorld()->GetTimeSeconds();
	FallingStartLocation = GetActorLocation();
    // 开启计时器
	GetWorldTimerManager().SetTimer(TickFallingHandle, this, &ATetrisBlock::TickFalling, 0.001f, true);

	float FallDistance = 0;
    // 获取要移动到的位置
	FallDistance = FallingStartLocation.Z -GetFallingEndLocation().Z;

	TotalFallingTime = 0.0f;
    // 根据速度计算下落时间
	if (TileMoveSpeed > 0.0f)
		TotalFallingTime = FallDistance / TileMoveSpeed;
    // 没有时间按0.75s算 
	if (TotalFallingTime <= 0.0f)
		TotalFallingTime = 0.75f;
}
  1. TickFalling()每帧实现步长的移动
void ATetrisBlock::TickFalling()
{
	float FallCompleteFraction = (GetWorld()->GetTimeSeconds() - FallingStartTime) / TotalFallingTime;
	// 如果我们在最终位置,请停止坠落。 否则,继续移动
	if (FallCompleteFraction >= 1.0f)
	{
		FinishFalling();
	}
	else
	{
		FVector NewLocation = FMath::Lerp(FallingStartLocation, FallingEndLocation, FallCompleteFraction);
		SetActorLocation(NewLocation);
	}
}
  1. 动画完成结束计时器
void ATetrisBlock::FinishFalling()
{
	// 停定时器
	GetWorldTimerManager().ClearTimer(TickFallingHandle);
	SetActorLocation(FallingEndLocation);
}

GENERATED_UCLASS_BODYGENERATED_BODY

在生成类后,.h文件中会自动添加宏,但会有两种不同的宏可以添加。这两个类都是来控制构造函数相关的操作。

GENERATED_UCLASS_BODY
4.17都会使用此宏,这个宏可以.h文件中不用定义构造函数,而在.cpp文件中直接声明它。但是在声明中要加入部分代码。

// -- -- -- TestGameMode.h
	//...
	GENERATED_UCLASS_BODY()

// -- -- -- TestGameMode.cpp
ATestGameMode::ATestGameMode (const FObjectInitializer& ObjectInitializer) 
: Super(ObjectInitializer)
{
	// ...
}

GENERATED_BODY
4.17统一使用些宏。如果需要构造函数,需要自己声明,而且这个构造函数必须是无参的。同时实现时也不用加额外代码。

// -- -- -- TestGameMode.h
	//...
	GENERATED_BODY()
private:
	ATestGameMode(); // 这里要声明

// -- -- -- TestGameMode.cpp
ATestGameMode::ATestGameMode()
{
	// ...
}

UWorld如何获得

在很多情况下,如果UGameplayStatics::GetPlayerController()需要获取当前
const UObject* WorldContextObject也就是世界的上下文对象的指针。

  • 如果是在集成于AActor的情况下,可以直接使用如下:
/** Getter for the cached world pointer, will return null if the actor is not actually spawned in a level */
virtual UWorld* GetWorld() const override;
// 这个是写在AActor文件中的
  • 如果其他情况,如果自己写的类或SlateWidget类中等等。
    World.cpp会有一个全局的变量来作为引用。
/** Global world pointer */
UWorldProxy GWorld;

新建对象与资源加载

新建

在c++中我们需要新建一个东西,不同的东西新建方法不一样。

Component:

UStaticMeshComponent* StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>("StaticMeshComp");
StaticMeshComp->SetupAttachment(RootComponent);

UObject

NewObject<...>(...)

Actor

GetWorld()->SpawnActor(...);

其他粒子、声音等

UGameplayStatics::SpawnObject();// UObjcet对象
UGameplayStatics::SpawnSound2D();// 2d音效
UGameplayStatics::SpawnEmitterAttached();//粒子
UGameplayStatics::SpawnDecalAtLocation();//贴花

资源加载

加载UObject资源

// 只在构造函数里使用
ConstructorHelpers::FObjectFinder<T> 
// 任何地方使用
LoadObject<T>

蓝图资源加载

// 只在构造函数里使用
ConstructorHelpers::FClassFinder<T> 
// 任何地方使用
LoadClass<T>

其中蓝图资源路径一定要加上 _C

有些函数名称前会有K2的前缀

在调用有些函数时,些函数的名称带有K2的前缀,如

ACamera Camera;
Camera->K2_GetComponentLocation(); // 获取组件位置 

这个表示调用的与蓝图中的函数是同一个。

Widget里鼠标点击事件

FReply ClassName::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
	SCompoundWidget::OnMouseButtonDown(MyGeometry, MouseEvent);
	// 这样也能获得当前鼠标在换算后的ViewPort上的位置
	MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()) 
}

评论