[程式] UE4 揭密SpawnActor的BP节点

楼主: yekdniw (yekdniw)   2019-01-12 13:52:10
网页版
https://yekdniwunrealengine.blogspot.com/2019/01/spawnactorbp.html
在BP的SpawnActor节点有个厉害的功能
就是你给不同的class type的话,这个节点会根据class type产生不同的样貌,
主要有两个:
1. return的actor type会是你传入的class type,而不是基础type actor,
还要自己cast
2. 如果传入的class有expose on spawn的变量,也会再这里列举出来让你可以传入
在说明细节之前,我们先看一下C++处理 expose on spawn的变量值是如何设定的。
AMyActor* pActor = SpawnActorDeferred;
// Fill your variable here...
FinishSpawningActor(pActor);
所以可以知道其实spawn一个拥有expose on spawn的actor是要作上述三个步骤的。
Spawn -> SetProperties -> FinishSpawn
如果因为某些因素没呼叫到最后的FinishSpawn,程式的运作就会有问题。
而BP的SpawnActorFromClass只用了一个节点就作到上述三件事情,
为了理解其中的奥妙,我花了一些时间追查,在这边分享一下。
程式码在
Engine\Source\Editor\BlueprintGraph\Classes\K2Node_SpawnActorFromClass.h
在function ExpandNode里面,就是处理一个节点其实会分成三大节点的主函式。
static const FName BeginSpawningBlueprintFuncName =
GET_FUNCTION_NAME_CHECKED(
UGameplayStatics,
BeginDeferredActorSpawnFromClass);
static const FName FinishSpawningFuncName =
GET_FUNCTION_NAME_CHECKED(
UGameplayStatics,
FinishSpawningActor);
上面两行可以看到会从UGameplayStatics之中
取出BeginDeferredActorSpawnFromClass以及FinishSpawningActor
的两个函式名称出来。
代表SpawnActor的节点实际上在Spawn跟FinishSpawn阶段就是对应到呼叫
BeginDeferredActorSpawnFromClass以及FinishSpawningActor
[图1.]
上面这段定义SpawnActor这个BP节点会有的各个连接点
[图2.]
上面这段定义呼叫
UGameplayStatics::BeginDeferredActorSpawnFromClass的各个连接点
接下来的程式码就是把SpawnActor的各个连接点,
一个个导向CallBeginSpawnNode的各个连接点。
使用的主要函式是CompilerContext.MovePinLinksToIntermediate
[图3.]
上面这段定义呼叫UGameplayStatics::FinishSpawningActor的各个连接点
图中如果有需要最外层的连接点连向CallFinishSpawnNode,可以使用
CompilerContext.CopyPinLinksToIntermediate
例如
CompilerContext.CopyPinLinksToIntermediate(
*CallBeginTransform,
*CallFinishTransform);
就是把外部传入的Transform座标一路往后带到FinishSpawningActor函式内
最后,处理expose on spawn的部分在这一行
UEdGraphPin* LastThen =
FKismetCompilerUtilities::GenerateAssignmentNodes(
CompilerContext,
SourceGraph,
CallBeginSpawnNode,
SpawnNode,
CallBeginResult,
ClassToSpawn );
里面会根据传入的class,找到class内有expose on spawn的properties,
然后根据这些properties建立set variable节点
函式最后一行SpawnNode->BreakAllNodeLinks();
把原来的结点所有的连结断掉,因为我们已经把使用者看到的节点
SpawnNode替换成三大节点:
CallBeginSpawnNode -> AssignmentNodes -> CallFinishSpawnNode
从这次的经验可以学习到,BP节点拥有节点替换的功能,
也就是说有的时候你看到一个节点,其实背后是有可能多作你不知道的事情。
这点可以多多拿来利用。
实际上程式码很多看起来很恐怖,不过慢慢看的话其实不算是太难懂的东西。
这边作个纪录也顺便分享一下学到的东西。
作者: InvincibleK (我是无敌的K)   2019-01-12 18:48:00
感谢分享
作者: coolrobin (泳圈)   2019-01-12 23:52:00
推推
作者: nickchu35 (尼克邱)   2019-01-13 14:30:00
推,UE source code 有时间钻真的会学到很多

Links booklink

Contact Us: admin [ a t ] ucptt.com