Actor replication

Hello !

For a weapon system, I wanna replicate a reference to an Actor (in my Character, I have a variable which is the equiped weapon). bReplicates is true on both Character and Weapon. So, I spawn the actor on server, then send is to the clients using NetMulticast, with a pointer to the weapon as a parameter. When I check the parameter in client function, it is ok, and I set the local pointer to the weapon to the parameter’s value. But then, after leaving the function, the pointer becomes nullptr, even if both actors still exist in the world. Is there anything to do?

Thanks !

EDIT: Source code in comment

You send the actor to the clients using NetMulticast…?

I think we need to see your code.

No, I mean, I send a pointer to it, because UE4 permits to send pointers to actors

Note: AXOOYDCharacter is the class of the character, AXOOYDWeapon is the base class for weapons (weapons instances are from a subclass). ResetInventory is called by BeginPlay only on server (dedicated server). Inventory is a TArray of AXOOYDWeapon*, CurrentWeapon is a AXOOYDWeapon*, DefaultInventory is a TArray of TSubClassOf.

As said previously, NewEquipedWeapon is not nullptr, and the display name is the same as the one in server.

XOOYDCharacter.h:

// Resets the inventory : destroys all the weapons and creates the default weapons
UFUNCTION()
void ResetInventory();

// Notifies all the clients that the inventory was reset
UFUNCTION(NetMulticast, Reliable)
void Client_OnResetInventory(const TArray<AXOOYDWeapon*>& NewWeapons, AXOOYDWeapon* NewEquipedWeapon);

XOOYDCharacter.cpp:

void AXOOYDCharacter::ResetInventory()
{
	CurrentWeapon = nullptr;
	for (auto Weapon : Inventory)
	{
		Weapon->Destroy();
	}

	Inventory.Empty();

	for (auto WeaponClass : DefaultInventory)
	{
		Inventory.Add(GetWorld()->SpawnActor<AXOOYDWeapon>(WeaponClass));
	}

	if (Inventory.Num() > 0)
	{
		CurrentWeapon = Inventory[0];
	}

	Client_OnResetInventory(Inventory, CurrentWeapon);
}


void AXOOYDCharacter::Client_OnResetInventory_Implementation(const TArray<AXOOYDWeapon*>& NewWeapons, AXOOYDWeapon* NewEquipedWeapon)
{
	CurrentWeapon = NewEquipedWeapon;

	for (auto InventoryWeapon : Inventory)
	{
		if (InventoryWeapon)
		{
			InventoryWeapon->Destroy();
		}
	}

	Inventory.Empty();
	Inventory.Append(NewWeapons);
}

You may find that the actor hasn’t properly replicated yet. There’s an OnReplicationInit function or something on actors, you could try using that to add it to the inventory.

I didn’t find such a function, but I think I got the point : I have to wait until UE4 performs all the replication-initialization related stuff, and then, it will correctly replicate

However, if you know such a function, please tell me :slight_smile:

Thanks a lot!

It’s this one, sorry.

Basically, the problem was the architecture : UE4 is not made for manual replication, I mean, passing pointers as function parameters in order to store them.

The right way to do an inventory system was to replicate CurrentWeapon and Inventory, with an OnRep. Manual replication is not the “UE4 way” to do this. So, I corrected my mistakes, and then, it worked !

I got this idea when I saw the ShooterProject’s source code, and I think it’s a great ressource for learning !