Issue: Nested SceneComponent Does Not Show In Game
English
If you try to make a USceneComponent
class, named A, creating, encapsulating and holding a reference to another USceneComponent
B, you may find that B cannot show in the game.
As we all know, when we try to add a component to Actor
, we must call AttachToComponent(RootComponent)
and RegisterComponent()
. That’s right.
But if you make a nested USceneComponent
, remind that when you add this class to an Actor, you should not only call the outer USceneComponent
‘s RegisterComponent
, but also the inner’s.
BTW, do not try to call the inner USceneComponent
‘s RegisterComponent()
in the outer’s constructor, which may cause error.
Chinese
最近遇到个需求,需要把两个UStaticMeshComponent
封装到一个SceneComponent
中。
假设我们新建了USceneComponent
类A,然后A持有两个UMeshComponent
B和C。
1 | class UA : public USceneComponent |
然后在某个Actor中,动态Add A(在)。
1 | void AMyActor::AddShape() |
然后发现游戏运行之后一直没有显示出来两个Mesh。
此时我还不知道RegisterComponent()
是干啥用的,总之就尝试先在A创建B和C之后先执行它们的RegisterComponent()
。
结果:
- B和C能显示出来了
- B和C没法跟着Actor的移动而移动
- 重新开启Editor的时候会报错,说是
RegisterComponent
不能在构造函数线程里调用:if (ensure(MyOwnerWorld))
这句话说明现在的World还没生成,或者没有Owner
于是又换了中写法,把B和C的RegisterComponent
放到外头,在A被创建完毕之后再执行。
结果一切正常了。
结论
当出现SceneComponent再嵌套了其他SceneComponent的时候,如果要把它加到Actor上,这里面所有的SceneComponent都得执行一次RegisterComponent
。
概念区分
RegisterComponent
把控件注册到世界。不注册的话会没办法被tick和render,无法显示出来而且不会执行任何tick逻辑。
所以动态创建完控件之后一定要调用一下RegisterComponent()
。
神奇的是,如果Component是在Actor的构造函数中通过CreateDefaultSubobject()
创建的,那么不执行RegisterComponent()
也能够正常运行。
AttachToComponent, AttachTo, SetupAttachment
AttachToComponent
是组件绑定,绑定到父类。要在非构造函数里面使用,如果在构造函数里面使用了,会发出一个警告,并且最终实际调用的是SetupAttachment
。
AttachTo
和AttachToComponent
是一样的结果,看源码可以发现它实际上调用的就是AttachToComponent
,但是已经deprecated,如果调用,编译器会发出警告。
SetupAttachment
在构造函数中被调用,用来先标记要attach到哪个parent。