I’ve inherited some code on our project from a team member who has left, and I’m trying to resolve an issue with the replication graph that has been set up.
In our game, players can pick up items from the floor and equip them, and also drop them for others to pick up.
In the replication graph, inventory items are defined in InitGlobalActorClassSettings() as having EClassReplicationNode as Spatialize_Static, because they don’t have any physics applied to them, or the ability to move when not held by the player.
Like in the ShooterGame example, we have a broadcast which is used to notify when an item is picked up or dropped. When picked up, the weapon is removed from the static list and added to the character as a dependent actor. When dropped, it is removed. However, because we want the weapon to appear on the floor for others to see and pick up, we also add it back to the list of static items. We also set the NetDormancy to DormantAll, because there is no need for it to replicate any information once it’s lying on the floor. It’s basically a static object waiting to be picked up by someone.
I have also a requirement to be able to destroy an item in a player’s inventory. This is for thrown weapons where once the weapon “fires” and the projectile is launched, we want to destroy it so it looks like it left the player’s hand. This is done by having the player drop the weapon first (so that it runs the code to update their inventory, switch to a new item etc.), then attempting to destroy it after 0.1s
The trouble is that whenever I try to destroy the weapon, it generates an ensure failure as below:
LogOutputDevice: Error: Ensure condition failed: IsActorValidForReplication(Actor) [File:E:/Epic Games/Unreal Source/Source-UnrealEngine-4.24/Engine/Plugins/Runtime/ReplicationGraph/Source/Private/ReplicationGraph.cpp] [Line: 1681] LogOutputDevice: Error: Actor not valid for replication (BeingDestroyed:1) (PendingKill:1) (Unreachable:0) (TearOff:0)! Actor = Weapon_Grenade_BP_C /Game/Maps/UEDPIE_1_New_Alpha_Map.New_Alpha_Map:PersistentLevel.Weapon_Grenade_BP_2, Channel = None
Here is the full list of steps used to “destroy” the item in the player’s inventory:
Item starts as being dependent on the owning character for replication. Net dormancy is Awake. All steps are done on the server unless noted
- Detach the weapon from the character mesh
- Enable collision on the weapon and make sure it’s not hidden anymore as part of the dropping code, so players can pick it up again
- Force Net Update on the item
- Set the owner to nullptr
- Set the net dormancy to DormantAll
- Flush Net Dormancy
- Broadcast the dropped action to the replication graph
- Place the item on the ground, set appropriate rotation etc
- Remove the item reference from the inventory, switch to a new item if there is on in the inventory etc.
Code then executes in the rep graph in response to the broadcast in step 7 above:
- Remove the dependency on the character
- Add the actor to the static list
Item is now on the static list, no dependency on character, Net dormancy is DormantAll
- Set the lifespan to 0.1s so it gets destroyed on the server and clients
I have also tried calling tearoff, and setting the lifespan to 0.1 in the TornOff() event. This however leads to endless warning spam on the server about how it cannot initialise a new object because it’s no longer set to replicate.
Can anyone help me smooth out this process so it works nicely? Looking at the above steps I see some potentially questionable steps (timing of setting NetDormancy, forcing net updates etc.), but ultimately I have no idea why it gives errors and warnings when attempting to destroy the item.