UEC++第10天|UEC++获取对象、RTTI是C++

发布于:2025-05-01 ⋅ 阅读:(33) ⋅ 点赞:(0)

最近在写UEC项目,这里写几个案例里的问题,还在学习阶段

1. 如何获取小鸟对象?

void AFlappyBirdGameModeBase::BeginGame() { 
 // 让管道动起来
 PipeActor->SetMoveSpeed();
 // 让小鸟开始飞行
 // 如何获取到小鸟对象
 APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0); // 第一个参数是世界内容,用来查找世界中的对象,用来搜索世界
 ABirdPawn* Bird = Cast<ABirdPawn>(Pawn);
 if(Bird) { 
 	Bird -> ChangeBirdState(EBirdState::EBS_Fly);
 }
}

前置知识

  1. C++ 类与函数:理解类的定义、成员函数,这里AFlappyBirdGameModeBase是一个类,BeginGame是其成员函数。
  2. 指针PipeActorPawnBird等都是指针,用于指向对象。
  3. 虚幻引擎相关知识UGameplayStatics是虚幻引擎提供的实用工具类,Cast是虚幻引擎中的类型转换函数,EBirdState是自定义枚举类型。

代码解释

这段代码在游戏模式AFlappyBirdGameModeBase开始游戏时执行。用途是初始化游戏中管道和小鸟的初始状态。首先通过PipeActor->SetMoveSpeed();让管道具备移动速度,然后通过UGameplayStatics::GetPlayerPawn获取玩家控制的角色(小鸟),转换为ABirdPawn类型指针Bird,若转换成功则调用ChangeBirdState函数让小鸟进入飞行状态。

简单代码示例

// 假设 ABirdPawn 类定义
class ABirdPawn : public APawn {
public:
    UENUM(BlueprintType)
    enum class EBirdState : uint8 {
        EBS_None,
        EBS_Fly,
        EBS_Die
    };
    void ChangeBirdState(EBirdState NewState);
};

// 假设 PipeActor 类定义
class APipeActor : public AActor {
public:
    void SetMoveSpeed();
};

class AFlappyBirdGameModeBase : public AGameModeBase {
public:
    APipeActor* PipeActor;
    virtual void BeginGame() override;
};

void AFlappyBirdGameModeBase::BeginGame() {
    PipeActor->SetMoveSpeed();
    APawn* Pawn = UGameplayStatics::GetPlayerPawn(this, 0);
    ABirdPawn* Bird = Cast<ABirdPawn>(Pawn);
    if (Bird) {
        Bird->ChangeBirdState(ABirdPawn::EBS_Fly);
    }
}

常见错误或误解及避免方法

  1. PipeActor未初始化:误解认为声明指针就可直接调用函数。避免方法是在使用PipeActor前确保其指向有效的APipeActor对象。
  2. 类型转换失败Cast可能失败,初学者可能忽略检查Bird是否为空指针。避免方法是在使用Bird前总是检查是否转换成功。
  3. UGameplayStatics::GetPlayerPawn参数错误:对第一个参数this理解错误,若不是从AGameModeBase派生类调用会出错。确保在合适的上下文调用此函数。

实际应用场景

  1. 游戏初始化: 在任何有动态移动障碍物和可操控角色的游戏开始时,都可设置初始状态。
  2. 关卡切换:当切换到包含飞行生物和移动障碍物的关卡时,用于初始化这些元素状态。

基本原理

BeginGame函数在游戏模式开始时自动调用。通过指针操作对象,PipeActor指针调用SetMoveSpeed设置管道移动速度。利用UGameplayStatics::GetPlayerPawn在游戏世界中查找玩家控制的PawnCast将其转换为特定类型ABirdPawn,若成功则可调用ABirdPawn特有的ChangeBirdState函数改变小鸟状态。

2. 上面代码的语法可以怎么简化,简化成什么样子

如下面代码所示:

if(ABirdPawn* Bird = Cast<ABirdPawn>(UGameplayStatics::GetPlayPawn(this, 0))) { 
}

3.RTTI是C++中面向对象的类型转换

前置知识

了解C++中类的定义以及成员变量和成员函数,类与类之间的继承关系,派生类如何冲基类中继承属性和行为。

掌握指针是一个变量,在RTTI中常通过指针或引用操作对象。还需要掌握 虚函数在派生类中被重写,通过基类指针引用虚函数的时候,会根据对象的实际类型来决定调用哪个版本的函数,实现多态。

在运行获取对象的实际的类型,在使用基类指针或实际引用操作对象的时候了解到对象的实际派生类型。

4.用什么关键字检查?动态类型转换。

在 C++ 中,动态类型转换使用dynamic_cast关键字。用途是在运行时进行安全的类型转换,主要用于将基类指针或引用转换为派生类指针或引用。

在C++中,动态类型转换使用dynamic_cast关键字,在运行进行安全的类型转换。主要用途是将基类指针或引用转换为派生类指针或引用。

#include <iostream>

class Base {
public:
    virtual void print() {
        std::cout << "This is Base class" << std::endl;
    }
};

class Derived : public Base {
public:
    void print() override {
        std::cout << "This is Derived class" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    Derived* derivedPtr = dynamic_cast<Derived*>(basePtr);
    if (derivedPtr) {
        derivedPtr->print();
    }
    delete basePtr;
    return 0;
}

这里是每天回答三个问题

如果觉得对你有帮助的话

麻烦点一个赞