虚幻4的actor相当于一个容器,各个功能都包含在组建当中。下面就总结一下虚幻4创建组建的各个方式

虚幻4的组建创建大概可以分为两类,一类是预创建,还有一种是动态创建。

第一类: 在构造函数中创建各个组件。蓝图直接用编辑器的AddComponent ,而c++则要事先声明UPROPERTY(BlueprintReadWrite,VisibleAnywhere,Category=“yourCategories”)如果是在private或者protected权限下要改变为

UPROPERTY(BlueprintReadWrite,VisibleAnywhere,Category=“yourCategories”,meta=(AllowPrivateAccess=“true”))

如果把VisibleAnywhere改为EditAnywhere你就会发现很多组件参数你不能在编辑器中看到了。然后在构造函数中调用CreateDefaultSubobject<UYourComponentClass>(TEXT("ComponentName"))。有个特殊的组建PhysicalConstrain在创建时必须指认actor1和actor2,不然会出现错误警告。

第二类就是运行时动态创建component 如果是蓝图就直接addcomponent就可以了。c++的话:

创建了继承自Actor的类,Spawn后没有rootcomponent,没有transform信息。

测试2:

发现rootcomponent为空。

CreateDefaultSubobject<USceneComponent>是否管用。

失败,这个函数只能在构造函数里面调用。

注释:不想在构造函数里增加Component,因为我想动态增加component;

测试3:

RootComponent = NewObject<USceneComponent>();
AddInstanceComponent(RootComponent);


失败

测试4:

ChildActorComponent = NewObject<UChildActorComponent>();
AddInstanceComponent(ChildActorComponent);

失败,连scenecomponent显示都没有了。

测试5:

DefaultRootComponent = NewObject<USceneComponent>();
AddInstanceComponent(DefaultRootComponent);

失败,同上。

测试6:

DefaultRootComponent = Cast<USceneComponent>( AddComponent("Root", true, FTransform(), NewObject<USceneComponent>()));
SetRootComponent(DefaultRootComponent);

失败,同上。

测试7:

尝试在构造函数里面添加ROOT,然后在其他函数里面Attach到root上面。

RootComponent= CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));

继承自Actor的rootcomponent可以显示,但是不能更改里面数值。尝试使用自己的变量:


定义:

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AItemInScene")
USceneComponent* DefaultRootComponent;

构造函数:

DefaultRootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
SetRootComponent(DefaultRootComponent);

可以显示Root了,也能更改数值。

测试8:

尝试在root上增加component:

ChildActorComponent = NewObject<UChildActorComponent>();
ChildActorComponent->AttachTo(DefaultRootComponent);

失败,root下什么也没显示。

测试9:

是否是要AddComponent()

ChildActorComponent = NewObject<UChildActorComponent>();
AddInstanceComponent(ChildActorComponent);

失败,root下什么也没显示。

测试10:

ChildActorComponent = NewObject<UChildActorComponent>(this, "name", RF_NoFlags, nullptr, false, nullptr);
ChildActorComponent->AttachTo(DefaultRootComponent, "name", EAttachLocation::KeepRelativeOffset, false);

成功,我想应该是创建时候NewObject的参数问题。

测试11:

DefaultRootComponent = NewObject<USceneComponent>(this, "root", RF_NoFlags, nullptr, false, nullptr);
ChildActorComponent = NewObject<UChildActorComponent>(this, "name", RF_NoFlags, nullptr, false, nullptr);
ChildActorComponent->AttachTo(DefaultRootComponent, "name", EAttachLocation::KeepRelativeOffset, false);

成功。但是组件里面的参数不能改,而且没有在Actor显示出来


测试12:

DefaultRootComponent = NewObject<USceneComponent>(this, "root", RF_NoFlags, nullptr, false, nullptr);
ChildActorComponent = NewObject<UChildActorComponent>(this, "name", RF_NoFlags, nullptr, false, nullptr);
AddInstanceComponent(DefaultRootComponent);
AddInstanceComponent(ChildActorComponent);

成功,解决所有问题。

StaticMeshComponent要想在世界中显示,要RegisterComponent

StaticMeshComponent->RegisterComponent();


组建创建完成之后,如果这个组建不是根组建记得把这个组建附加到根组建上。4.11使用attachto()  4.12以后的引擎版本使用SetupAttachment()


虚幻4可以使用插件,虽然现在的插件不多,但是仍有个问题。如果我想使用外部的c++插件组建的话怎么办呢,比如cablecomponent。

虚幻4官方的建议是不要让插件模块和游戏模块代码静态链接。我们可以使用蓝图充当胶水将各个模块连接起来。当然也可以静态链接。以cablecomponent

为例,首先需要在工程的build.cs里把这个模块加进游戏模块。当然前提是这个插件允许被添加。然后在yourproject.h包含插件头文件即可。


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐