Replicating Weapons so They Appear

I have no idea how to fix this issue. The server initializes every player’s inventory. I then proceeds to place both weapons on the back. I marked them as “replicate” but they are not showing up on the client side:

Below is my header file where I declare the weapons, sockets and inventory inside my character:

	/** socket or bone name for attaching weapon mesh */
	UPROPERTY(EditDefaultsOnly, Category = Inventory)
	FName WeaponAttachPoint;

	/** socket or bone name for attaching Utility mesh */
	UPROPERTY(EditDefaultsOnly, Category = Inventory)
	FName OffHandAttachPoint;

	/** socket or bone name for attaching Utility mesh */
	UPROPERTY(EditDefaultsOnly, Category = Inventory)
	FName OffWeaponAttachPoint;

	/** socket or bone name for attaching Utility mesh */
	UPROPERTY(EditDefaultsOnly, Category = Inventory)
	FName MainWeaponAttachPoint;

	/** default inventory list */
	UPROPERTY(EditDefaultsOnly, Category = Inventory)
	TArray<TSubclassOf<class AArenaRangedWeapon>> DefaultInventoryClasses;

	/** weapons in inventory */
	UPROPERTY(Transient, Replicated)
	TArray<class AArenaRangedWeapon*> Inventory;

	/** play weapon animations */
	float PlayWeaponAnimation(UAnimMontage* Animation);

	/** currently equipped weapon */
	UPROPERTY(Transient, ReplicatedUsing = OnRep_CurrentWeapon)
	class AArenaRangedWeapon* CurrentWeapon;

	class AArenaRangedWeapon* LastWeapon;

	class AArenaRangedWeapon* NewWeapon;

	/** currently equipped weapon */
	UPROPERTY(ReplicatedUsing = OnRep_PrimaryWeapon)
	class AArenaRangedWeapon* PrimaryWeapon;

	/** currently equipped weapon */
	UPROPERTY(ReplicatedUsing = OnRep_SecondaryWeapon)
	class AArenaRangedWeapon* SecondaryWeapon;

This is how I initialize the players:

if (Role == ROLE_Authority)
	{
		IdleTime = 0.0f;
		bInCombat = false;
		PlayerConfig.Health = GetMaxHealth();
		PlayerConfig.Stamina = GetMaxStamina();
		PlayerConfig.Energy = GetMaxEnergy();
		SpawnDefaultInventory();
	}

void AArenaCharacter::SpawnDefaultInventory()
{
	if (Role < ROLE_Authority)
	{
		return;
	}

	int32 NumWeaponClasses = 2; //DefaultInventoryClasses.Num();
	for (int32 i = 0; i < NumWeaponClasses; i++)
	{
		if (DefaultInventoryClasses[i])
		{
			FActorSpawnParameters SpawnInfo;
			SpawnInfo.bNoCollisionFail = true;
			AArenaRangedWeapon* NewWeapon = GetWorld()->SpawnActor<AArenaRangedWeapon>(DefaultInventoryClasses[i], SpawnInfo);
			AddWeapon(NewWeapon);
		}
	}

	// equip first weapon in inventory
	if (Inventory.Num() > 0)
	{
		PrimaryWeapon = Inventory[0];
		PrimaryWeapon->SetIsPrimaryWeapon(true);
		SecondaryWeapon = Inventory[1];
		InitializeWeapons(PrimaryWeapon, SecondaryWeapon);
	}
}

void AArenaCharacter::InitializeWeapons(AArenaRangedWeapon* mainWeapon, AArenaRangedWeapon* offWeapon)
{
	mainWeapon->OnHolster(true);
	offWeapon->OnHolster(false);
}

Going into my Weapon class to see the holster:

void AArenaRangedWeapon::OnHolster(bool IsPrimary)
{
		if (MyPawn)
		{
			// For locally controller players we attach both weapons and let the bOnlyOwnerSee, bOwnerNoSee flags deal with visibility.
			FName AttachPoint;
			if (IsPrimary == true)
			{
				bPendingHolster = true;

				float Duration = PlayWeaponAnimation(HolsterAnim);
				if (Duration <= 0.0f)
				{
					Duration = 0.5f;
				}

				GetWorldTimerManager().SetTimer(this, &AArenaRangedWeapon::OnHolsterPrimary, FMath::Max(0.1f, Duration - 0.70f), false);
			}
			if (IsPrimary == false)
			{
				bPendingHolster = true;

				float Duration = PlayWeaponAnimation(HolsterAnim);
				if (Duration <= 0.0f)
				{
					Duration = 0.5f;
				}

				GetWorldTimerManager().SetTimer(this, &AArenaRangedWeapon::OnHolsterSecondary, FMath::Max(0.1f, Duration - 0.70f), false);
			}
		}
	}
}

void AArenaRangedWeapon::OnHolsterPrimary()
{
	if (MyPawn)
	{
		// Remove and hide both first and third person meshes
		DetachMeshFromPawn();

		FName AttachPoint = MyPawn->GetMainWeaponAttachPoint();

		// For locally controller players we attach both weapons and let the bOnlyOwnerSee, bOwnerNoSee flags deal with visibility.
		if (MyPawn->IsLocallyControlled() == true)
		{
			USkeletalMeshComponent* PawnMesh3p = MyPawn->GetPawnMesh();
			Mesh3P->SetHiddenInGame(false);
			Mesh3P->AttachTo(PawnMesh3p, AttachPoint);
		}
		else
		{
			USkeletalMeshComponent* UseWeaponMesh = GetWeaponMesh();
			USkeletalMeshComponent* UsePawnMesh = MyPawn->GetPawnMesh();
			UseWeaponMesh->AttachTo(UsePawnMesh, AttachPoint);
			UseWeaponMesh->SetHiddenInGame(false);
		}
	}

	bIsEquipped = false;
	bPendingEquip = false;
}

I would be grateful for any insight

Assuming your weapon is actor and you want to attach it to another actor (character).

You need to call this from AttachRootComponentTo() from weapon actor, and as parameter provide mesh from character.

Remember that you must do it on server!, Attachment will be replicated automatically.

Thanks for the reply! I gave it a try but still nothing. The weird thing is when I actually equip the weapon, it appears in my hand. It is almost like the “holster” sockets don’t replicate across the server. I feel like I am missing something super obvious.

At you specifying sockets name in Defaults ?(in class constructor or in blueprint defaults).

This is how my attachment function looks:

void AGSCharacter::AttachActor(AActor* ActorIn, FName SocketNameIn)
{
	if (ActorIn)
	{
		ActorIn->DetachRootComponentFromParent();
		ActorIn->AttachRootComponentTo(GetMesh(), SocketNameIn, EAttachLocation::SnapToTarget, true);
	}
}

It’s called on server. So make sure, you do all related stuff on server, and that weapon it’s self is also replicated.

Okay I found the issue. There were a few things:

  1. I have numerous checks if (Role == ROLE_Authority). Though the server did call he function is was not able to get past these checks

  2. I had a check if (MyPawn). I forgot to say Weapon->SetOwningPawn(this) before unequipping, Which is why I could equip weapons but not unequip them.

Thanks so much for you help!