[Iris] Actors placed or spawned in the world before a connection exists do not support delta compression

Hello,

We ran into an issue trying to apply delta compression to an actor in our level. When we spawn the actor at runtime when a player has already connected, this class/actor will have delta compression applied. If it was spawned or placed in the level before any connection exists, the delta compression does not get applied.

From debugging this issue I believe I tracked the issue down.

The function FDeltaCompressionBaselineManager::UpdateScope calls AllocPerObjectInfoForObject for objects that were not previously in scope, but are in scope now. Is uses NetRefHandleManager->GetPrevFrameScopableInternalIndices() for this, this is updated in OnPostSendUpdate, done every frame at the end of the frame. AllocPerObjectInfoForObject ends up setting ObjectIndexToObjectInfoIndex, which is required for FDeltaCompressionBaselineManager::CreateBaseline to create a baseline for those delta compressed objects.

But UpdateScope is called from FDeltaCompressionBaselineManager::PreSendUpdate, which is conditionally called from UReplicationSystem::NetUpdate. The condition for this is if (bAllowObjectReplication && bUpdateConnectionSpecifics).

This condition will fail if we have no connections active.

If we have actors spawned or placed in the world, when no connections exist, they will be set in PrevFrameScopableInternalIndices at the end of the frame, without ever going into UpdateScope. Thus, the moment we receive a connection, and we enter UpdateScope, PreviousScopable already contains the actors which were placed in the world or spawned before a connection existed, and never end up calling AllocPerObjectInfoForObject because it is not considered an object that just came into scope.

To confirm this is the case I set bAllowMinimalUpdateIfNoConnections to false, so that UpdateScope is always entered when no connections exist, and this fixes the issue.

Is this a known issue, or is there a fix you can suggest to us without us needed to set the option to false?

Kind regards,

Céleste Neukirchen

Steps to Reproduce

  • Create an actor with replicating properties, register this actor class under DeltaCompressionConfigs.
  • Place the actor in the world
  • Play in PIE
  • Note that the actor has no delta compression applied
  • Spawn the same actor type after the client joined
  • Note that the second actor has delta compression, the originally placed one does not.

Hi,

Thank you for bringing this to our attention!

I don’t believe this is a known issue, and so I’ve created a new issue for this, UE-333873, which should be visible in the public tracker in a day or so.

Thanks,

Alex

Hi,

Thanks for reporting the issue. The minimal update was created mainly for listen servers where the update cost when no players had joined could be substantial so it’s just an optimization. It’s just an oversight that the delta compression isn’t working as expected. If you’re not using listen servers or don’t see any performance issues with it I’d recommend disabling the minimal update until the bug is fixed.

Cheers,

Peter

Hey Alex,

Thanks for confirming it’s an issue. Is there any solution to this in the meantime other than disabling minimal updates?

Do we need to be concerned about toggling that off? Considering it only affects Iris when there’s no connections, I don’t really see any performance implication in our game as it’s multiplayer-heavy. But in the off chance this has side effects I’d like to know.

Otherwise, would a fix be to store another list of PreviousInScopeObjects inside the baseline manager and only compare to the one inside the baseline manager? Then set the PreviousInScopeObjects to InScopeObjects of the NetRefHandleManager at the end of the frame?

Hi,

I’m going to loop in someone more familiar with Iris to get their input on potential workarounds/fixes.

Thanks,

Alex