I want to replicate an Actor that has SpawnActor
. How can I do that?
I’ve created a player’s weapon system that allows the player to equip items onto their weapon. However, this functionality doesn’t work in multiplayer, mainly because the weapon is created using SpawnActor
at BeginPlay
based on a DataAsset. So, I tried spawning it only on the server and replicating the value, but I still get null on the client side.
The ActionComponent has DataObjects registered for replication, and within these DataObjects, weapon data (Attachment, Equipment, DoAction) is registered. Both of them have Replicates
set to true. Then, I use DataAssets to spawn the actual Actor and assign it. My expectation is that replication should occur during this assignment process, but the client doesn’t respond.
Here My Code:
this is DataObject
CActionObjectContainer.cpp
void ACActionObjectContainer::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ACActionObjectContainer, Attachment);
DOREPLIFETIME(ACActionObjectContainer, Equipment);
DOREPLIFETIME(ACActionObjectContainer, DoAction);
DOREPLIFETIME(ACActionObjectContainer, EquipmentColor);
}
CActionComponent.h
private:
UPROPERTY(EditDefaultsOnly)
class UCActionData* Datas[(int32)EActionType::Max];
UPROPERTY(Replicated)
TArray<class ACActionObjectContainer*> DataObjects;
CActionComponent.cpp
void UCActionComponent::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(UCActionComponent, Type);
DOREPLIFETIME(UCActionComponent, DataObjects);
}
UCActionComponent::UCActionComponent()
{
DataObjects.SetNum((int32)EActionType::Max);
PrimaryComponentTick.bCanEverTick = true;
SetIsReplicatedByDefault(true);
}
void UCActionComponent::BeginPlay()
{
if (!!charcater && charcater->HasAuthority())
{
for (int i = 0; i < (int32)EActionType::Max; ++i)
{
if (!!Datas[i])
{
// DataAsset`s Custom BeginPlay
//SpawnActor Attachment, Equipment, DoAction
Datas[i]->BeginPlay(charcater, &DataObjects[i], i);
}
}
}
}
CActionData.cpp
void UCActionData::BeginPlay(ACharacter* InOwnerCharacter, ACActionObjectContainer** OutObject, int32 Index)
{
FTransform transform;
ACAttachment* Attachment = nullptr;
ACEquipment* Equipment = nullptr;
ACDoAction* DoAction = nullptr;
UCAttachmentStatusComponent* AttachmentStatusComp = nullptr;
/* SpawnActor Attachment, Equipment, DoAction...
if (!!AttachmentClass)
{
Attachment = InOwnerCharacter->GetWorld()->SpawnActorDeferred<ACAttachment>(AttachmentClass, transform, InOwnerCharacter);
Attachment->Tags.Add(FName(*(GetLabelName(InOwnerCharacter, "Attachment"))));
Attachment->SetRole(OwnerRole);
Attachment->bNetUseOwnerRelevancy = true;
#if WITH_EDITOR
Attachment->SetActorLabel(GetLabelName(InOwnerCharacter, "Attachment"));
#endif
UGameplayStatics::FinishSpawningActor(Attachment, transform); // 얘는 상속받은 위치에서 AttachTo 함
}
//CEquipment 생성: Character 만 World가 있기에
if (!!Attachment)
{
AttachmentStatusComp = NewObject<UCAttachmentStatusComponent>(Attachment, UCAttachmentStatusComponent::StaticClass(), TEXT("AttachmentStatus"));
if (!!AttachmentStatusComp)
{
Attachment->SetAttachmentStatusComponent(AttachmentStatusComp);
AttachmentStatusComp->InitStatus(Attachment->AttachmentStatusData);
}
}
if (!!EquipmentClass)
{
Equipment = InOwnerCharacter->GetWorld()->SpawnActorDeferred<ACEquipment>(EquipmentClass, transform, InOwnerCharacter);
Equipment->SetData(EquipmentData);
Equipment->SetColor(EquipmentColor);
Equipment->SetRole(OwnerRole);
Equipment->bNetUseOwnerRelevancy = true;
Equipment->Tags.Add(FName(*(GetLabelName(InOwnerCharacter, "Equipment"))));
#if WITH_EDITOR
Equipment->SetActorLabel(GetLabelName(InOwnerCharacter, "Equipment"));
#endif
UGameplayStatics::FinishSpawningActor(Equipment, transform);
Equipment->AttachToComponent(InOwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true));
}
if (!!Attachment && !!Equipment) {
Equipment->OnEquipmentDelegate.AddDynamic(Attachment, &ACAttachment::OnEquip);
Equipment->OnUnequipmentDelegate.AddDynamic(Attachment, &ACAttachment::OnUnequip);
}
if (!!DoActionClass)
{
DoAction = InOwnerCharacter->GetWorld()->SpawnActorDeferred<ACDoAction>(DoActionClass, transform, InOwnerCharacter);
DoAction->AttachToComponent(InOwnerCharacter->GetMesh(), FAttachmentTransformRules(EAttachmentRule::KeepRelative, true));
DoAction->SetRole(OwnerRole);
DoAction->bNetUseOwnerRelevancy = true;
DoAction->SetDatas(DoActionDatas);
DoAction->SetStrongData(StrongData);
DoAction->SetGuardData(BlockData);
DoAction->SetParryData(ParryData);
DoAction->SetParryDamageType(ParryDamageType);
DoAction->SetMyIndex(Index);
DoAction->Tags.Add(FName(*(GetLabelName(InOwnerCharacter, "DoAction"))));
#if WITH_EDITOR
DoAction->SetActorLabel(GetLabelName(InOwnerCharacter, "DoAction"));
#endif
UGameplayStatics::FinishSpawningActor(DoAction, transform);
if (!!Attachment)
{
Attachment->OnAttachmentBeginOverlap.AddDynamic(DoAction, &ACDoAction::OnAttachmentBeginOverlap);
Attachment->OnAttachmentEndOverlap.AddDynamic(DoAction, &ACDoAction::OnAttachmentEndOverlap);
}
}//end if
FActorSpawnParameters SpawnParams;
*/
*OutObject = InOwnerCharacter->GetWorld()->SpawnActorDeferred<ACActionObjectContainer>(ACActionObjectContainer::StaticClass(), transform, InOwnerCharacter);
(*OutObject)->SetOwnerCharacter(InOwnerCharacter);
(*OutObject)->Attachment = Attachment;
(*OutObject)->Equipment = Equipment;
(*OutObject)->DoAction = DoAction;
(*OutObject)->EquipmentColor = EquipmentColor;
UGameplayStatics::FinishSpawningActor(*OutObject, FTransform());
}