UE中对象创建方法示例和类的理解

33 篇文章 4 订阅

对象创建方法示例集

        创建Actor示例

//创建一个护甲道具
AProp* armor = GetWorld()->SpawnActor<AProp>(pos, rotator); 

        创建Component示例

UCapsuleComponent* CapsuleComponent = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComponent"));

        创建加载资源对象示例

UStaticMesh* chairMesh = Cast<UStaticMesh>(
    StaticLoadObject(UStaticMesh::StaticClass(),  
    NULL,  
    TEXT("/Game/Assets/Props/StaticMeshe/ChairMesh")));  

UStaticMeshComponent* StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));  
StaticMesh ->SetStaticMesh(chairMesh);

        创建UObject示例

UItemBase* ItemCopy = NewObject<UItemBase>(StaticClass());

        在上面的创建加载资源对象和UObject示例中都出现了StaticCalss()方法,下面就说说相关的内容。

关于StaticClass、GetClass和ClassDefaultObject

UClass和反射

        什么是反射?

反射的作用是在不知道这个类的情况下获取到它的信息 。

        UC++底层实现了一套反射机制。

        先看C#怎么用反射:

string s = "Hello,guys!”;
Type t = s.GetType();

        Type里面就包含了string这个类的各种信息。

UClass就是C#里的Type。

        UClass和C#里的Type的作用不完全相同,可以这么理解。

GetClass()

        GetClass() 类似C#的GetType。        

类静态方法获取StatiClass

UClass* PropUClass = APropArmor::StaticClass();

 如何知道一个UClass和另一个UClass是不是继承关系? 

        UClass存储了它要描述的类的父类的StaticClass。 举例说明:假如有个MyActor类的UClass,想知道MyActor是不是UObject的子类,可以这么做:

  • 调用UObject::StaticClass()
  • 拿到MyActor的UClass存储的MyActor的父类的StaticClass也就是Actor的StaticClass
  • 比较Actor的StaticClass和UObject的StaticClass是不是相等
  • 发现不相等,这次我拿Actor的StaticClass(因为它也是一个UClass)里存的Actor父类的StaticClass也就是UObject的StaticClass,然后比较,发现相等,返回true
  • 如果我发现不相等,我就一直比,比到最后没有父类,返回false

上面这段逻辑就是UClass的IsChildOf的实现原理。调用IsChildOf的时候传入泛型:

这是具体实现。UStruct是UClass父类。

GetSuperStruct()就是返回它存储的父类的StaticClass。

顺带再讲一下IsA这个函数,功能和IsChildOf一样,不同的是IsChildOf给UClass用的,IsA是给UObject对象实例用的,比如想知道一个MyActor实例是不是UObject的子类:

//myActor是MyAcor*类型
bool result = myActor->IsA<UObject>();

ClassDefaultObject

        ClassDefaultObject(简称CDO),类默认对象。

通过CDO我可以拿到一个UObject初始化时的值。

        虽然CDO有个Default默认,但是用默认去描述它的功能不是很准确。回到我们创建的类MyActor,给它添加一个外部可以修改变量testIntValue,默认值1:

        对于两个蓝图分别修改,一个20,另一个10:

        然后在BeginPlay写下测试代码:

//先修改值再获取ClassDefaultObject
testIntValue = -1;
auto defaultInt = GetClass()->GetDefaultObject<AMyActor>()->testIntValue;
UE_LOG(LogTemp, Warning, TEXT("DefaultObject int: %d"), defaultInt);

        最后打印的结果是一个20,一个10。
        如果想拿到代码里给它设的默认值1要用StaticClass

auto staticDefaultInt = AMyActor::StaticClass()->GetDefaultObject<AMyActor>()->testIntValue;
//打印1
UE_LOG(LogTemp, Warning, TEXT("StaticDefaultObject int: %d"), staticDefaultInt);

总结

  • UClass。存储类信息,用于反射。把它当成C#的Type来理解。
  • GetClass()。获得一个UObject实例的UClass,是UObject成员函数。
  • GetStaticClass()。不需要有实例就能获得UClass。是静态的,每次调用返回相同结果。
  • ClassDefaultObject。类默认对象,可以获得UObject初始化时的值。注意GetClass()->GetDefaultObject()和T::StaticClass()->GetDefaultObject()不一样。

参考链接:Unreal Engine 4 C++ 创建对象的几种方法_uec++创建对象-CSDN博客

参考链接:【UE·底层篇】一文搞懂StaticClass、GetClass和ClassDefaultObject - 知乎

  • 26
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UE4,根据不同的别,有不同的方法创建对象。 对于继承自UObject但不继承自Actor的,我们可以使用NewObject函数来创建对象。例如,我们可以创建一个UObjectClass对象,代码如下: ```cpp UObjectClass* MyClass = NewObject<UObjectClass>(); ``` 这样创建对象将由UE4引擎来管理。 对于纯C++(即非继承自UObject的,一般以F开头),我们可以使用new关键字来创建对象,并使用TSharedPtr和TSharedRef来管理对象。例如,我们可以创建一个MyClass对象,代码如下: ```cpp TSharedPtr<MyClass> MyClassPtr = MakeShareable(new MyClass()); ``` 这样创建对象将由TSharedPtr来进行引用计数,并在不再需要时自动释放内存。 对于继承自UObject的组件,我们也可以像创建UObject子一样使用NewObject函数来创建组件对象。但是,创建组件后,我们需要使用RegisterComponent或RegisterAllComponents函数将其注册才能使其生效。例如,我们可以创建一个UStaticMeshComponent的组件对象,并注册到当前对象上,代码如下: ```cpp UStaticMeshComponent* MyMeshComp = NewObject<UStaticMeshComponent>(this, TEXT("MyMeshComp")); MyMeshComp->SetupAttachment(RootComponent); MyMeshComp->SetRelativeLocation(FVector(0.f, 0.f, 0.f)); UStaticMesh* StaticMesh = LoadObject<UStaticMesh>(NULL, TEXT("StaticMesh'/Game/StaticMesh.StaticMesh'")); MyMeshComp->SetStaticMesh(StaticMesh); MyMeshComp->RegisterComponent(); ``` 这样创建的组件对象将由UE4引擎来管理,并在适当的时候进行更新和渲染。 总结起来,UE4创建对象方法根据别的不同而不同。对于继承自UObject的,我们可以使用NewObject函数来创建对象;对于纯C++,我们可以使用new关键字来创建对象,并使用TSharedPtr和TSharedRef来管理对象;对于继承自UObject的组件,我们可以使用NewObject函数来创建组件对象,并使用RegisterComponent或RegisterAllComponents函数将其注册。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值