一些容易忘的知识,但最近要用

枚举

enum DAY  
{
 MON=1, TUE, WED, THU, FRI, SAT, SUN 
};

位置

GetTransform()/GetActorLocation:获取位置

Actor:

FVector NewLocation = GetActorLocation();
FRotator NewRotation = GetActorRotation();

时间

GetGameTimeSinceCreation();

文字输出

打印到日志

UE_LOG(LogTemp, log, TEXT("普通信息,不会中断程序"));
UE_LOG(LogTemp, Warning, TEXT("警告: %d"), 123);
UE_LOG(LogTemp, Error, TEXT("错误: %f"), 123.0);
UE_LOG(LogTemp, Fatal, TEXT("致命错误: %s"), "Oh no");

DEBUG_LOG("角色速度:%f", Speed);
//DEBUG_LOG会展开成
//UE_LOG(LogTemp, Warning, TEXT("角色速度:%f"), Speed);

多个参数

UE_LOG(LogTemp, log, TEXT("x: %f \ny: %f"), X,Y);

参数解释

UE_LOG(
	LogTemp,//一个日志类别,表示临时调试信息
	Warning, //日志等级
	TEXT("Hello %d"),// 内容
	123//`Format` 和 `__VA_ARGS__`(可变参数),替换%d
	);

打印到屏幕

首先要检查指针,因为GEngine只在游戏已经开始后才存在。(BeginPlay()Tick()里是OK的,但构造函数里不行)

if (GEngine){}

下面是两种方式

GEngine->AddOnScreenDebugMessage(-1,3.0f,FColor::Red,TEXT("!"));

FString Name = "Hello World!";
GEngine->AddOnScreenDebugMessage(-1,3.0f,FColor::Red, Name);

参数解释

GEngine->AddOnScreenDebugMessage(
        -1,                    // Key(-1:新建一条,1:覆盖旧的)
        3.0f,                  // 显示时间(3秒),“.0f”表示长存
        FColor::Yellow,        // 字体颜色
        TEXT("Hello World!")   // 显示内容
    );

清空屏幕

GEngine->ClearOnScreenDebugMessages();

为了防止文字出现在正式版中,应该写在

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
if (GEngine)         //这里的代码
{                    //不在发布版 (Shipping)
	GEngine->        //和测试版 (Test) 
}                    //中运行
#endif

只在开发版(Debug) 和 调试版(DebugGame)执行。

创建对象

创建

UCameraComponent* Camera = NewObject<UCameraComponent>(this);
AMyActor* Actor = GetWorld()->SpawnActor<AMyActor>();

类的引用:TSubclassOf

UPROPERTY(EditAnywhere)
TSubclassOf<AWeapon> WeaponClass;  //在蓝图中选择一个继承AWeapon的类

AWeapon* Weapon = GetWorld()->SpawnActor<AWeapon>(WeaponClass);  

遍历场景中的对象

TActorIterator:高效

#include "EngineUtils.h" 
	 //有参构造一个该类型的迭代器It
for (TActorIterator<AMyActor> It(GetWorld()); It; ++It)
{
    AMyActor* obj = *It;//用obj接收
}

GetAllActorsOfClass:比较麻烦的是,第三个参数数组只能是AActor,需转类型

TArray<AActor*> FoundActors;//基类数组
UGameplayStatics::GetAllActorsOfClass(GetWorld(),AMyActor::StaticClass(), FoundActors);

TArray<AMyActor*> MyActors;//目标类数组
for (AActor* Actor : FoundActors)
{
    AMyActor* AyActor = Cast<AMyActor>(Actor);//把基类转成目标类
    if (AyActor)
    {
        MyActors.Add(AyActor);
    }
}

加载资源

//加载骨骼网格体
static ConstructorHelpers::FObjectFinder<USkeletalMesh> TankMeshAsset(TEXT("/Game/SK_West_Tank_M1A1Abrams.SK_West_Tank_M1A1Abrams"));
if (TankMeshAsset.Succeeded())
{
    GetMesh()->SetSkeletalMesh(TankMeshAsset.Object);
}

//加载静态网格体
static ConstructorHelpers::FObjectFinder<UStaticMesh> TankDamagedMeshAsset(TEXT("/Game/West_Tank_M1A1Abrams/Damaged/SM_West_Tank_M1A1Abrams_Damaged.SM_West_Tank_M1A1Abrams_Damaged"));
if (TankDamagedMeshAsset.Succeeded())
{
    TankDamagedMesh->SetStaticMesh(TankDamagedMeshAsset.Object);
}

//加载动画蓝图
static ConstructorHelpers::FClassFinder<UMyVehicleAnimationInstance> AnimInstanceAsset(TEXT("/Game/ABP_MyVehicleAnimationInstance.ABP_MyVehicleAnimationInstance_C'"));
if (TankDamagedMeshAsset.Succeeded())                   
{
    GetMesh()->SetAnimInstanceClass(AnimInstanceAsset.Class);
}


//加载增强输入上下文
static ConstructorHelpers::FObjectFinder<UInputMappingContext> ContextObj(TEXT("/Game/IMC_MyTank.IMC_MyTank"));
if (ContextObj.Succeeded() && ContextObj.Object) { MappingContext = ContextObj.Object; }

static ConstructorHelpers::FObjectFinder<UInputAction> IA_Move(TEXT("/Game/IA_Move.IA_Move"));
if (IA_Move.Succeeded() && IA_Move.Object) { MoveAction = IA_Move.Object; }

委托

类型描述关键字
单播委托只能绑定一个函数后绑定覆盖前绑定DECLARE_DELEGATEDECLARE_DELEGATE_OneParam
动态单播委托可暴露给蓝图,绑定一个函数DECLARE_DYNAMIC_DELEGATE
多播委托可绑定多个函数DECLARE_MULTICAST_DELEGATE
动态多播委托蓝图可绑定多个函数DECLARE_DYNAMIC_MULTICAST_DELEGATE

✅ 1. 单播委托

声明:

DECLARE_DELEGATE(FSimpleDelegate);

DECLARE_DELEGATE_OneParam(FOneParamDelegate, int32);
                  FSimpleDelegate MyDelegate;

绑定:

MyDelegate.BindUObject(this, &MyClass::MyFunction);//本类,本函数

解绑:

MyDelegate.Unbind();

广播:

if (MyDelegate.IsBound())
{
    MyDelegate.Execute();
}
//或
MyDelegate.ExecuteIfBound();

✅ 2. 动态单播委托(可用于蓝图)

声明:

DECLARE_DYNAMIC_DELEGATE(FDynamicSimpleDelegate);
DECLARE_DYNAMIC_DELEGATE_OneParam(FDynamicOneParamDelegate, int32, Param);
				FDynamicSimpleDelegate MyDelegate;

绑定:

MyDelegate.BindDynamic(this, &MyClass::MyFunction);

解绑:

MyDelegate.Unbind();

广播:

if (MyDelegate.IsBound()) 
{
    MyDelegate.Execute();
}

✅ 3. 多播委托(单播委托的数组)

声明:

DECLARE_MULTICAST_DELEGATE(FMultiDelegate);
DECLARE_MULTICAST_DELEGATE_OneParam(FMultiDelegateOneParam, int32);
					FMultiDelegate MyDelegate;

绑定:


MyDelegate.AddUObject(this, &MyClass::MyFunction);

解绑:

MyDelegate.RemoveAll(this);

广播:

MyDelegate.Broadcast();  // 广播所有绑定者,有参委托就在括号里写参数

✅ 4. 动态多播委托(最常用于蓝图)

声明:

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicMulticastDelegate);

声明时必须是 UPROPERTY:

				UPROPERTY(BlueprintAssignable)
				FDynamicMulticastDelegate OnNotify;

绑定:

OnNotify.AddDynamic(this, &MyClass::MyFunction);

解绑:

OnNotify.RemoveDynamic(this, &MyClass::MyFunction);

广播:

OnNotify.Broadcast();

一种 “匿名函数” ——当写代码的时候需要一个函数,可以在原地临时定义一个小函数并立刻传进去,常用于回调函数

[捕获列表](参数列表) -> 返回类型 {
    函数体
};

Lambda 让你临时写函数更方便,不用专门定义一个独立函数

✨ 捕获列表详细

写法说明
[]不捕获任何外部变量
[=]捕获外部变量(包括 this)按值拷贝
[&]捕获外部变量 按引用,可以修改它们
[this]捕获当前类的成员变量
[var1, &var2]精确指定:var1 按值,var2 按引用

FString

FString 的创建方式

1. 直接构造

FString MyStr = TEXT("Hello");
FString MyString1 = FString(TEXT("Hello"));

FString MyString2 = FString(OtherString); // 拷贝构造

2. 类型转换

FString MyStr = MyText.ToString();//从FText
FString MyStr = MyName.ToString();//从FName

3. 字符串拼接

FString Result = FString(TEXT("Hello")) + TEXT(" World");

4. 通过格式化

FString Formatted = FString::Printf(TEXT("Value: %d"), 42);

5. 从其他类型转换

int32 Number = 100;
FString NumString = FString::FromInt(Number);

FText

1. 直接构造

#define LOCTEXT_NAMESPACE "YourNamespace"  // 放在文件顶部(通常是.cpp)

FText Text = LOCTEXT("HelloKey", "Hello, World!");

#undef LOCTEXT_NAMESPACE  // 放在文件末尾

//`LOCTEXT` 宏依赖于你所在文件中定义了 `LOCTEXT_NAMESPACE` 宏,它是告诉 Unreal "这个文件属于哪个本地化命名空间"。
FText FromNumber = FText::AsNumber(123);

2. 类型转换

FText MyText = FText::FromString(MyStr);//从FString

FText MyText = FText::FromString(FString(TEXT("Hello")));//同上

FText MyText = FText::FromName(MyName);//从FName

FText MyText = FText::FromName(FName("PlayerName"));//同上

FName

1. 直接构造

FName Name = FName("Enemy_001");

2. 类型转换

FName MyName = FName(*Str); //从FString 注意需要用 * 解引用

FName MyName = FName(*Text.ToString());//从FText 用 * 解引用
转换方法示例
FStringFName*运算符*MyString
FStringconst TCHAR**运算符*MyString
const char*FStringTEXT()TEXT("string")
FNameFString.ToString()MyName.ToString()

按键绑定和输入

头文件

public:
    // 输入对象
   	/** 映射上下文*/
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputMappingContext* MappingContext;

   	/** 输入类 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* MoveAction;

	/** 触发类 */
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
	UInputAction* FireAction;

protected:

	//输入函数
	UFUNCTION()
	void Move_Forward(const FInputActionValue& Value);

    UFUNCTION()
	void Turn_Right(const FInputActionValue& Value);

    UFUNCTION()
	void Action_UnFire();

	virtual void NotifyControllerChanged() override;//控制器更换时调用
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

cpp

加载资源

AMyPawn::AMyPawn()
{
        static ConstructorHelpers::FObjectFinder<UInputMappingContext> ContextObj(TEXT("/Game/My/Input/IMC_MyTank.IMC_MyTank"));
    if (ContextObj.Succeeded() && ContextObj.Object) { MappingContext = ContextObj.Object; }

    static ConstructorHelpers::FObjectFinder<UInputAction> IA_Move(TEXT("/Game/My/Input/Actions/IA_Move.IA_Move"));
    if (IA_Move.Succeeded() && IA_Move.Object) { MoveAction = IA_Move.Object; }

    static ConstructorHelpers::FObjectFinder<UInputAction> IA_Look(TEXT("/Game/My/Input/Actions/IA_Look.IA_Look"));
    if (IA_Move.Succeeded() && IA_Move.Object) { LookAction = IA_Look.Object; }

    static ConstructorHelpers::FObjectFinder<UInputAction> IA_Interact(TEXT("/Game/My/Input/Actions/IA_Fire.IA_Fire"));
    if (IA_Move.Succeeded() && IA_Move.Object) { FireAction = IA_Interact.Object; }
}

绑定

void AMyPawn::NotifyControllerChanged()
{
    Super::NotifyControllerChanged();

    // 绑定映射上下文
    if (APlayerController* PlayerController = Cast<APlayerController>(Controller))
    {
        if (UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(PlayerController->GetLocalPlayer()))
        {
            Subsystem->AddMappingContext(MappingContext, 0);
        }
    }
}

void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
    Super::SetupPlayerInputComponent(PlayerInputComponent);

    // 绑定动作映射与函数
    if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
        // Move
        EnhancedInputComponent->BindAction(MoveAction, ETriggerEvent::Triggered, this, &AMy_Tank::Move_Forward);

        // Fire
        EnhancedInputComponent->BindAction(FireAction, ETriggerEvent::Started, this, &AMy_Tank::Action_Fire);
    }
}

处理输入

void AMyPawn::Move_Forward(const FInputActionValue& Value)
{
	FVector2D MovementVector = Value.Get<FVector2D>();//获取输入的值(两个)

    float Distance = MovementVector.Y;//获取Y方向的值

	const FRotator Rotation = Controller->GetControlRotation();//获取控制器的旋转

	const FRotator YawRotation(0, Rotation.Yaw, 0);//只保留旋转的Yaw轴

	FRotationMatrix RotMatrix(YawRotation);//创建旋转矩阵,描述旋转后的坐标轴
	const FVector ForwardDirection = RotMatrix.GetUnitAxis(EAxis::Y);//获取新坐标轴的Y轴方向,即前方

	AddMovementInput(ForwardDirection,Distance );//往ForwardDirection方向移动Distance 
}

碰撞筛选

碰撞通道(TraceChannel)和碰撞查询参数(CollisionQueryParams

一个是粗略筛选,一个是精细筛选

碰撞通道:

虚幻引擎预定义了多种碰撞通道,例如:ECC 是 Engine Collision Channel

枚举值说明
ECC_WorldStatic静态物体(如地形、建筑)。
ECC_WorldDynamic动态物体(如可移动的物体)。
ECC_Pawn角色(玩家、NPC)。
ECC_Visibility用于可见性检测(如鼠标点击选中)。
ECC_Camera摄像机碰撞检测。
ECC_PhysicsBody启动物理的刚体。
ECC_Vehicle载具专用通道。
ECC_Destructible可破坏物体。

自定义碰撞通道

#define MyChannel ECC_GameTraceChannel1 //引擎提供了18个自定义的检测通道,这是1

碰撞查询参数:

碰撞通道筛选后才查看查询参数

FCollisionQueryParams 是 一个结构体,可以用其创建对象作为查询参数传入

FCollisionQueryParams Params;
Params.AddIgnoredActor(MyActor); // 忽略MyActor
Params.bTraceComplex = true;     // 启用复杂碰撞

GetWorld()->LineTraceSingleByChannel(..., Params, ...);

FCollisionQueryParams 的核心成员

成员/方法类型说明
AddIgnoredActor()void忽略特定Actor(不检测它)。
AddIgnoredComponent()void忽略特定组件(如某个Mesh)。
bTraceComplexbool是否启用复杂碰撞检测(精确到三角形级别,默认false)。
bReturnPhysicalMaterialbool是否在FHitResult中返回物理材质(默认false)。
bDebugQuerybool是否在调试视图中绘制检测射线(默认false)。
TraceTagFName自定义标签(用于区分不同类型的检测)。

定时器(带lambda函数)


FTimerHandle TimerHandle;
GetWorld()->GetTimerManager().SetTimer(
	TimerHandle,
	[this]() // 捕获this指针
	{
		//在这里写代码,不要引用外部函数的对象,lambda函数运行时,外部对象早释放了
	},
	0.2f, // 延迟0.2秒
	false // 一次性定时器
	);

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值