UnrealEngin C++小知识点
删除C++的类
- 打开工程目录
Source
>工程名文件夹
>删除要删的类Binaries
文件夹删除工程名.uproject
右键Generate Visual Studio Project Files
工程名.uproject
右键Open
- 提示缺失文件是否重新生成,选是
UE4输出日志的方法
- 在UE4中蓝图里输出到屏幕里的节点是
printfString
- 在C++中,使用
- 这个方法好处,可以显示出当前打印出是谁调用的,在做网络游戏中很有用
// 要引入头文件
#include "Kismet/KismetSystemLibrary.h"
UkismetSystemLibrary::PrintString(this,TEXT("Hello World!"));
- 或使用
GEngin->Add
- 如果在
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; // 移动速度
- 使用
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;
}
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);
}
}
- 动画完成结束计时器
void ATetrisBlock::FinishFalling()
{
// 停定时器
GetWorldTimerManager().ClearTimer(TickFallingHandle);
SetActorLocation(FallingEndLocation);
}
GENERATED_UCLASS_BODY
与GENERATED_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())
}
评论