FNetworkPredictionServiceRegistry

Services do the actual system work on batches of registered instances.

Windows
MacOS
Linux

References

Module

NetworkPrediction

Header

/Engine/Plugins/Runtime/NetworkPrediction/Source/NetworkPrediction/Public/Services/NetworkPredictionServiceRegistry.h

Include

#include "Services/NetworkPredictionServiceRegistry.h"

Syntax

class FNetworkPredictionServiceRegistry

Remarks

Services do the actual system work on batches of registered instances. UNetworkPredictionWorldManager orchestrates them.

Services should treat all registered instances the same in most cases. Instead of 1 services that has different behavior based on Role/NetConnection/etc, make N services to cover each unique case. There will be exceptions to this where a role branch on a minor aspect of the service is better than creating a brand new service.

Services are defined by an interface (E.g, IFixedRollbackService) and a ModelDef based template implementation (E.g, TFixedRollbackService).

Services operate on the data stored in TModelDataStore, which is owned by the FNetworkPredictionServiceRegistry. All services get a pointer to the data store when created. Services are free to keep internal acceleration structures but should mainly operate on the per-instance data in the data store.

FNetworkPredictionServiceRegistry maintains lists of all active services. Services are bound to the ENetworkPredictionService enum for identification. The template implementations are instantiated on demand during registration where ModelDef::ID is the index into the TServiceStorage array.

The big picture looks like this, where 1=templated class has been instantiated and is managing X registered instances: [ModelDef::ID] [ServiceType] 0 1 2 3 4 5 ... N FixedRollback 1 0 1 1 1 0 FixedExtrapolated 0 1 0 0 1 0 ... IndependentFinalize 0 0 0 0 0 1

NPs instance are registered to X services based on their config and network role/connection. Subscribed services are stored in TInstanceData<ModelDef>::ServiceMask. As runtime settings change, E.g, NetworkLOD, the set of subscribed services will change. This is done efficiently with the ServiceMask.

Services are an implementation detail of the UNetworkPredictionWorldManager and should not be exposed directly to outside runtime code. E.g, don't pass pointers to services back to user code.

Services can be specialized on ModelDef types. This could facilitate more efficient batch processing or further per-simulation/modeldef customization. Services should have RegisterInstance/UnregisterInstance functions that take only the FNetworkPredictionID as parameter.

No direct cross-service communication. Services can have their own internal services (E.g, rollback has an internal tick service) but the "top level" services do not communicate. UNetworkPredictionWorldManager should coordinate things.

Adding new services:

Add entry to ENetworkPredictionService

Add NP_DECLARE_SERVICE

Add NP_DEFINE_SERVICE_CALL

Add logic to UNetworkPredictionWorldManager::ConfigureInstance to determine the conditions for subscribing to the service

Add logic in UNetworkPredictionWorldManager to actually invoke the service. This will obviously be service dependent.

New services types are not meant to be arbitrarily added by projects. Adding a brand new service requires modification of UNetworkPredictionWorldManager. If you want to tack on 'something special', look at specializing an existing service (E.g the tick service could do 'extra stuff' per tick for example).

Future Improvements: -All services template classes are currently instantiated for all ModelDefs (the templated code is generated for each ModelDef) -Even if ModelDefs are incompatible for a given service. E.g, a pure physics ModelDef with no Simulation still has the TLocalInputService<PhysicsModelDef> code instantiated. -To be clear: it does not instantiate an instance of TLocalInputService at runtime, but the code is generated and almost certainly cannot be culled by the compiler. -Concepts could be used to determine if ModelDefs are compatible with Services and we could avoid the template code instantiation. -This would add more template machinery, and basically requires all TService<ModelDefs> be hidden behind SFINAE walls. E.g, Factories for instantiating and CallOrNot for Register/Unregister. -Its not clear if its worth the effort at this point. In practice there should be relatively few ModelDefs that would benefit from this. -But it could make a difference in some cases for build time and exe size

Variables

Functions

Name Description

Public function

TModelDataSt...

 

GetDataStore()

DataStore

Public function

void

 

RegisterInstance

(
    FNetworkPredictionID ID,
    TInstanceData< ModelDef >& Instanc...,
    ENetworkPredictionService ServiceMa...
)

Registers instance with given services. Will unregister instance with any previously-subscribed services.

Public function

void

 

UnregisterInstance

(
    FNetworkPredictionID ID
)

Classes

Name

Description

Public struct

TServiceStorage

Services

Help shape the future of Unreal Engine documentation! Tell us how we're doing so we can serve you better.
Take our survey
Dismiss