Works perfectly in PIE/Standalone but fails in Packaged Build (Character mesh assignment / PlayerState replication)

Hello everyone,

I’m having a multiplayer issue that only happens in a packaged build. Everything works perfectly inside the editor (PIE, Standalone, and even late join), but the exact same logic fails after packaging.

Here’s how my system works:

  • I’m using a Listen Server with Steam Online Subsystem.
  • In my GameMode, inside Handle Starting New Player (I also tried OnPostLogin, same result), I cast the New Player output to my custom Character.
  • Then I cast to my custom PlayerState and assign a value to a replicated CharacterID variable.
  • After that, I cast to my custom PlayerController and add it to an AllPlayerControllers array.
  • After a 0.3 second delay, I cast to my GameState and update the player list.
  • The GameState stores the current PlayerArray inside a replicated RepNotify variable called AllPlayerStates.
  • Inside the OnRep function of AllPlayerStates, I loop through the players and assign the correct skeletal mesh based on each player’s CharacterID.

This entire system works perfectly in:

  • PIE
  • Standalone
  • Late Join inside the editor

However, in a Packaged Build, it does not work.

Both the host and the client always keep the default mesh. It looks like the mesh assignment never happens, or the CharacterID isn’t available when the mesh should be applied.

Things I’ve already tried:

  • Moving the logic from OnPostLogin to Handle Starting New Player.
  • Adding delays before updating the player list.
  • Using a RepNotify variable inside GameState.
  • Steam enabled and disabled (same behavior).

The strange part is that the exact same Blueprint logic works flawlessly inside the editor but consistently fails only in the packaged build.

Has anyone experienced different initialization or replication order between PIE and Packaged builds that could cause this? Is there a better way to synchronize character selection/mesh assignment across clients?

Any suggestions would be greatly appreciated.

Thanks!

Your likely issue is order of receival. Your code is based on the assumption that the character, controller are received on the client before the playerstate onrep is fired. Under real world conditions (packaged on WAN) there aren’t any guarantees when you’ll receive anything.

New Player is a Player Controller Obj Reference Casting to a Pawn will fail.

What you should be doing here, if you want to go this route, is using an Interface on the playerstate and passing a value to it.

The GameState contains an array of all playerstates. when you update a playerstate class, the GS PlayerArray gets updated. There’s know reason to loop the GS playerr array to update any playerstate. It’s already handled. Meaning every player will get a copy of the GS and its PlayerArray. Each playerstate in the array will have the latest states.


For character class cosmetics you want to set an Onrep in the character class itself. In that onrep you want it to do lookups and then assign/swap skeletal meshes, materials, abilities, gameplay tags etc.

You assign the cosmetics in the GM when the character is first spawned on the server.

Looping arrays and hoping a packet isn’t dropped or received in the correct order has a very high tendency to fail under real world conditions.