Actor组件可以扩展Actor的行为。Actor组件是一类特殊的对象,可以作为子对象附加到Actor上。Actor组件默认不会复制,但你可以配置任意Actor组件,使其作为其所属Actor的一部分进行复制。Actor组件可以复制自身属性和子对象,也可以像Actor那样调用由Actor组件类定义的远程过程调用(RPC)。
要将Actor组件作为Actor的一部分复制,必须确保:
- 将拥有该Actor组件的Actor设置为可复制。
- 将Actor组件设置为可复制。
Actor组件类型
静态Actor组件
静态Actor组件 在其所属Actor生成时生成。静态组件在Actor的C++结构函数中创建的默认子对象,或是在蓝图编辑器的组件模式中创建。
复制静态Actor组件
复制在Actor结构函数中创建的Actor组件,请按以下步骤操作:
- 在Actor结构函数中:
- 使用
bReplicates = true; 将Actor设置为可复制。
-
使用 CreateDefaultSubobject<T> 在Actor结构函数中创建Actor组件:
AMyActor::AMyActor()
{
bReplicates = true;
MyActorComponent = CreateDefaultSubobject<UMyActorComponent>(TEXT("MyActorComponent"));
}
- 在Actor组件结构函数中:
动态Actor组件
动态Actor组件 实在运行时在服务器上生成的Actor组件。动态Actor组件的创建或删除都会被复制到相连的客户端上。动态Actor组件的工作方式类似Actor。
客户端可以生成自有的、本地的、不可复制的动态Actor组件。
复制动态Actor组件
要复制在运行时动态创建的Actor组件,请按以下步骤操作:
- 在Actor结构函数中:
- 在想要复制新Actor组件时:
蓝图Actor组件
你可以在蓝图中生成静态和动态Actor组件。
复制静态蓝图Actor组件
要在蓝图中复制静态Actor组件,需在Actor组件的 细节面板 中开启 复制(Replicates) 布尔字段。只有当组件具有你想要复制的属性或事件,你才需要复制该Actor组件。
你可以在 细节面板 的 组件可复制性(Component Replication) 分段中奖一个Actor组件设置为默认可复制。
组件可复制性(Component Replication) 仅出现在支持某种形式复制功能的组件上。
复制动态蓝图Actor组件
要在蓝图中复制动态Actor组件,需要在开启 应复制(Should Replicate) 字段的前提下调用 Set Is Replicated 函数。
Begin Object Class=/Script/BlueprintGraph.K2Node_CustomEvent Name="K2Node_CustomEvent_0" ExportPath="/Script/BlueprintGraph.K2Node_CustomEvent'/Game/MyBlueprints/BP_MyActor.BP_MyActor:EventGraph.K2Node_CustomEvent_0'"
CustomFunctionName="Event ReplicateComponent"
NodePosY=681
NodeGuid=818B4FBA4AB8D2434CFAECA23B4FA1A1
CustomProperties Pin (PinId=421A30E3469187EF6B5740AE931D3780,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent="/Script/Engine.BlueprintGeneratedClass'/Game/MyBlueprints/BP_MyActor.BP_MyActor_C'",MemberName="Event ReplicateComponent",MemberGuid=818B4FBA4AB8D2434CFAECA23B4FA1A1),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=62D2FC444CA20DB5E9B3A8955CAC3E2E,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_0 06F6405B4C0EAC380F0686AAB61C9142,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
Begin Object Class=/Script/BlueprintGraph.K2Node_CallFunction Name="K2Node_CallFunction_0" ExportPath="/Script/BlueprintGraph.K2Node_CallFunction'/Game/MyBlueprints/BP_MyActor.BP_MyActor:EventGraph.K2Node_CallFunction_0'"
FunctionReference=(MemberParent="/Script/CoreUObject.Class'/Script/Engine.ActorComponent'",MemberName="SetIsReplicated")
NodePosX=416
NodePosY=681
NodeGuid=BF0399784595F2FE6960EB96EC2720C3
CustomProperties Pin (PinId=06F6405B4C0EAC380F0686AAB61C9142,PinName="execute",PinToolTip="\nExec",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CustomEvent_0 62D2FC444CA20DB5E9B3A8955CAC3E2E,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=B9CD644C4D6D4BA1C0974A9E6587E6C6,PinName="then",PinToolTip="\nExec",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=B3041B214B81F199F983ACB72C6313B4,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinToolTip="Target\nActor Component Object Reference",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/CoreUObject.Class'/Script/Engine.ActorComponent'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_VariableGet_0 148F62B441C32524EE4B75A258C6EDA3,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=63B137774CD10EC982E1EB9977EDDB2A,PinName="ShouldReplicate",PinToolTip="Should Replicate\nBoolean",PinType.PinCategory="bool",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,DefaultValue="true",AutogeneratedDefaultValue="false",PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
Begin Object Class=/Script/BlueprintGraph.K2Node_VariableGet Name="K2Node_VariableGet_0" ExportPath="/Script/BlueprintGraph.K2Node_VariableGet'/Game/MyBlueprints/BP_MyActor.BP_MyActor:EventGraph.K2Node_VariableGet_0'"
VariableReference=(MemberName="BP_MyActorComponent",bSelfContext=True)
NodePosX=128
NodePosY=784
NodeGuid=77ABE40B46D72F9B9E5F3CAF2525B65C
CustomProperties Pin (PinId=148F62B441C32524EE4B75A258C6EDA3,PinName="BP_MyActorComponent",Direction="EGPD_Output",PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/Engine.BlueprintGeneratedClass'/Game/MyBlueprints/BP_MyActorComponent.BP_MyActorComponent_C'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(K2Node_CallFunction_0 B3041B214B81F199F983ACB72C6313B4,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=2E0192B34CCBEC99A1F485B839A7E62D,PinName="self",PinFriendlyName=NSLOCTEXT("K2Node", "Target", "Target"),PinType.PinCategory="object",PinType.PinSubCategory="",PinType.PinSubCategoryObject="/Script/Engine.BlueprintGeneratedClass'/Game/MyBlueprints/BP_MyActor.BP_MyActor_C'",PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,PersistentGuid=00000000000000000000000000000000,bHidden=True,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
复制Actor组件属性
你可以用复制Actor属性的方法来复制Actor组件属性。关于复制Actor属性的详情,请参阅复制Actor属性一文。
Actor组件远程过程调用
你可以在Actor组件类中定义远程过程调用(RPC),并用调用ActorRPC的方式来调用它。关于定义、实现和调用RPC的详情,请参阅远程过程调用一文。
复制Actor组件子对象
Actor组件可以像Actor拥有自己的复制子对象列表。它们使用和Actor想通的API接口来注册和注销其子对象。Actor组件内的子对象也可以拥有复制条件。
在检查复制子对象的条件前,其所属组件必须先被复制到连接上。例如,如果子对象具有一个 COND_OwnerOnly 条件,但被注册到了一个使用 COND_SkipOwner 条件的组件上,那么该子对象将永远不会被复制,因为其所属组件会被跳过。
关于复制子对象的详情,请参阅复制Actor子对象一文。
带宽开销
Actor内每个被复制的Actor组件都会增加:
- 一个由4个字节组成的网络全局唯一标识符(NetGUID)标头。
- 所有复制的属性和空间需求。
- 一个约1字节长的脚标。
在考虑带宽开销时,需要注意三个地方:
- 复制:相比复制整个Actor,复制一个Actor组件上的一个属性的影响相对较小。
- 调用RPC:从Actor组件调用RPC的开销高于直接从Actor调用RPC。为了缓解这一情况,建议考虑通过Actor发送Actor组件RPC。具体示例请参阅角色移动组件一文。
- Actor组件数量:Actor组件相对较小。但如果你使用了大量组件和组件子对象,可能会降低性能。