What kind of Subsystems are replicated?

Subsystems are really cool, they keep things organized. But I don’t know how and when use them for replication.

Engine? I don’t see how this would be replicated.

Editor? I’m sure this is not replicated.

GameInstance? This would make sense up to a point, but I expect this not to be replicated.

LocalPlayer? This imo should be replicated.

Then there are types that are not in this doc like for example WorldSubsystem:

WorldSubsystem That would make the most sense to put objects that should be replicated to all the players.Espacially if they implement ReplicateSubobjects:

Can any help me understand the replication in each Subsystem?

Thanks very much.

1 Like

Hi,

Thanks for your answer. Not only Actors are replicated, UObjects can be replicated as long as they implement some methods. I have already done it. There are several examples among different official Modules. You have to implement this method in an object that is already replicating:

 virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;
 virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

And this in objects that aren’t replicated by default:

 virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;
 virtual bool IsSupportedForNetworking() const override { return true; }
 virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;

So the second one would depend on the first one to replicate.

The replication system focuses on replicating Actors, not subsystems. Here’s a good overview: Actor Replication | Unreal Engine Documentation

As for default Actors that are replicated:

  • GameState is replicated to all players so it’s a good place to put stuff like Time Left and maybe Scores
  • PlayerController is replicated to the “owning player”, which is the player that this controller relates to.
  • PlayerState is replicated to all players so this is a good place to store info about players that is relevant to everyone like Name etc.
  • Character is usually replicated to all players and is the visible character for each player.

Some of the Subsystems might replicate things, but it’ll be low level stuff that you shouldn’t need to worry about. If you need to replicate something, put it in one of the actors above or make a new actor and set it to replicate.

True, you can replicate a UObject but it has to be a subobject of an Actor. See how ReplicateSubobjects takes a UActorChannel*

Is there something specific in one of the subsystems you’d like to replicate?

And yes, making a quick search of that method, none of the subsystems are replicated, which in my opinion is a pity, since some of them share the lifetime of replicated Actors.

Yes, that’s true and compatible with my concern about not being able to replicate subsystems that share the lifetime of Actors such as Players (via APlayerController) or World (via AGameStateBase).

Thanks again for your help, I’m going to format all the gathered information into an answer. Thanks for helping me out.

None. By default none of the Subsystems are replicated. But you can replicate them.

If you want to replicate subsystems you have to make them dependent on the Class that shares the same lifetime and have that Actor implementing these methods. It works even if the Subsystem wasn’t created by the Replicating Actor but by the time it’s replicating that Actor Reference must be set, otherwise it won’t work. A good example would be having a WorldSubsystem and implementing a AGameStateBase that implements that replication.

virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;
  virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;

And your subsystem implementing these:

  virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const override;
  virtual bool IsSupportedForNetworking() const override { return true; }
  virtual bool ReplicateSubobjects(class UActorChannel *Channel, class FOutBunch *Bunch, FReplicationFlags *RepFlags) override;

Having that, in our AGameState we would have:

bool AMyGameState::ReplicateSubobjects(class UActorChannel* Channel, class FOutBunch* Bunch, FReplicationFlags* RepFlags)
{

	bool WroteSomething = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);

	if (MySubsystem)
	{
		WroteSomething |= Channel->ReplicateSubobject(MySubsystem, *Bunch, *RepFlags);
	}

	return WroteSomething;
}

And then in our subsystem:

bool UMySubsystem::ReplicateSubobjects(UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
	return false;
}

void UMySubsystem::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty >& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
	DOREPLIFETIME(UMySubsystem, Var);
}
1 Like

Subsystem are designed to encapsulate logic and make them reusable and independent without having to extend Engine classes that share the lifetime with. If I create a plugin and sell it on the Marketplace, I would need the users to implement my Actors whereas if I package it in a subsystem then Users can still use their own.

This is true for having multiple subsystems, then, if I don’t have them the logic of that Actors will increase and users would be force to choose which base class implementation would need. Which is currently hapening at the moment. Basically, most Plugins that you can buy force you to use their Engine base classes (GameMode, PlayerController, Pawn… etc).

You can make your own APlayerController and AGameStateBase subclasses and write whatever logic you want in there, no need to use a subsystem for it. You can specify which classes to use in your GameMode, you have full control over that stuff.

That’s a good point. I guess you could provide replicated components that users can add to their own custom classes but maybe not as powerful as a GameModeSubsystem would be