AttachRootComponentTo Replication?

Hello,

I’m trying to make a Flag (think as a CTF mode of sorts) that, when the player picks it up, it will attach to a socket in the player model. I thought this would be simple enough in theory, but I’m having a hard time to make it work.

Initially, I thought that simple setting it into the server would work. Sadly, it didn’t. Then I tried a naked NetMulticast function. Didn’t work. Then I tried a RPC to server. Didn’t work. Then I combined everything into a big RPC + NetMulticast. Still didn’t work.
It only happens on server side, as if the client never gets aware of the attachment.

I don’t know how to fix it. This is what I have now:

header

 //...

	UFUNCTION(NetMulticast, Reliable)
		void BroadcastAttachFlagToCharacter(class AMyCharacter* Character);
	virtual void BroadcastAttachFlagToCharacter_Implementation(class AMyCharacter* Character);

	/** Attach the flag to the supplied character */
	void AttachFlagToCharacter(AMyCharacter* Character);

	/** This set of functions handles (AttachFlagToCharacter) with network support. */
	UFUNCTION(Server, Reliable, WithValidation)
		void ServerAttachFlagToCharacter(AMyCharacter* Character);
	virtual void ServerAttachFlagToCharacter_Implementation(AMyCharacter* Character);
	virtual bool ServerAttachFlagToCharacter_Validate(AMyCharacter* Character);

	void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;

//...

cpp:

//////////////////////////////////////////////////////////////////////////
// Zoc (2015-05-28): Networked implementation of AttachFlagToCharacter(AMyCharacter* Character)
//////////////////////////////////////////////////////////////////////////
void ACTFFlag::AttachFlagToCharacter(AMyCharacter* Character)
{
	UE_LOG(MyCriticalErrors, Warning, TEXT("a message"), *(Character->GetName()));

	if (Role < ROLE_Authority)
	{
		ServerAttachFlagToCharacter(Character);
		return;
	}

	UE_LOG(MyCriticalErrors, Warning, TEXT("server message"), *(Character->GetName()));

	BroadcastAttachFlagToCharacter(Character);
}

void ACTFFlag::ServerAttachFlagToCharacter_Implementation(AMyCharacter* Character)
{
	AttachFlagToCharacter(Character);
}

bool ACTFFlag::ServerAttachFlagToCharacter_Validate(AMyCharacter* Character)
{
	return true;
}

void ACTFFlag::BroadcastAttachFlagToCharacter_Implementation(AMyCharacter* Character)
{
	if (Role < ROLE_Authority)
	{
		UE_LOG(MyCriticalErrors, Warning, TEXT("Messed up call"));
	}

	// DetachRootComponentFromParent();
	USkeletalMeshComponent* PawnMesh = Character->GetMesh();
	AttachRootComponentTo(PawnMesh, "FlagSocket", EAttachLocation::SnapToTarget);

}

void ACTFFlag::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	// Replicate to everyone
	DOREPLIFETIME(ACTFFlag, FlagMesh);
}

There’s some leftovers there (ue_log) that I won’t bother editing right now (sorry, I’m kinda tired and it’s late!)

One thing that’s good to notice is that the “server message” (debug message in a ue_log) just happens once. so the server is aware of the changes, I can see the flag attached in the listen/play-in-editor window, but can’t see it in the other windows.

Any advice on what I’m doing wrong?

Thanks in advance!

You need to do it in BroadcastAttachFlagToCharacter function, but you need to call BroadcastAttachFlagToCharacter function from ServerAttachFlagToCharacter function. Multicast functions must be called from server functions, not from client functions.

Client -> Server -> Multicast

Try this and say to me if it works! ^^

Hey Scienziatogm! Thank you for you input.
I did the BroadcastAttachFlagToCharacter() from ServerAttachFlagToCharacter_Implementation(), it didn’t work (actually, it didn’t update the status anywhere).

The way I setup the functions, anytime AttachFlagToCharacter() is called, it checks for the server authority. If it’s not the server calling it, call ServerAttachFlagToCharacter(), which then calls the AttachFlagToCharacter() function in the server.

So… I still have no idea how to do this properly :frowning:

If you call the AttachFlagToCharacter function in the server, it won’t work on the server. You need to execute the content of AttachFlagToCharacter in a server function.

I found this on https://github.com/EpicGames/UnrealTournament/blob/clean-master/UnrealTournament/Source/UnrealTournament/Public/UTCarriedObject.h


	// workaround for bug in AActor implementation
	virtual void OnRep_AttachmentReplication() override;
	// HACK: workaround for engine bug with transform replication when attaching/detaching things
	virtual void OnRep_ReplicatedMovement() override;


Are attachments really bugged? ><

I’m not sure I understood what you mean. Can you provide a code example of what should be done, or a modification of the code in the original post? :slight_smile:
Thanks in advance!


void ACTFFlag::AttachFlagToCharacter(AMyCharacter* Character)
{
    ServerAttachFlagToCharacter(Character);
}

void ACTFFlag::ServerAttachFlagToCharacter_Implementation(AMyCharacter* Character)
{
    BroadcastAttachFlagToCharacter(Character);
}

bool ACTFFlag::ServerAttachFlagToCharacter_Validate(AMyCharacter* Character)
{
    return true;
}

void ACTFFlag::BroadcastAttachFlagToCharacter_Implementation(AMyCharacter* Character)
{
    USkeletalMeshComponent* PawnMesh = Character->GetMesh();
    AttachRootComponentTo(PawnMesh, "FlagSocket", EAttachLocation::SnapToTarget);
}

Thank you. I tried this and it has the same behavior as my code :frowning:

Any other ideas? :slight_smile:

Where is AttachFlagToCharacter called?

@Scienziatogm Thank you for your support and patience!
Apparently, my code is correct, for some reason the replication checkboxes on the blueprint were disabled (even when I explicitly enabled them on C++!).
I can’t believe I took this long to pinpoint the problem.
Thank you a lot!

I just feel confused how that happened… Glad it’s solved :slight_smile:

Ok. All properties must be edited in C++ like a blueprint, because if you don’t edit them, they will have default values.