You mention actors that exist already in the level. This isn't a concept that has really applied to me as yet, because I have not considered a scenario where I would want level actors that aren't added depending upon the client connected. Could you possibly elaborate? I saw mention in the Unreal source but I wasn't sure when this would be useful to me.
Actors that already exist on the client would be those that are added to a level in the editor, which both the server and client would have a copy of in Unreal games.
The question reliability was specific to Unreal (or Tribes) with net priority; I was asking if that is the correct understanding of their model. Out of order delivery was asking how Unreal handles it (although this is related to the typical "How do I order an unreliable protocol"! I wouldn't mind simply dropping out of order packets except when there are delta variables (e.g the difference vector between two velocities) for more precision, which require access to the last state. Additionally, this does not seem to be how Unreal handles it.
I recommend using RakNet if possible because it can handle reliability issues for you. Unreal compresses its vectors send sends the full value over the Internet, not a delta from the last state. This way the packet can be ignored if it arrives late or not at all.
My other vague question was about the age of variables. It seems as though there is no specific support for determining the time for which the attributes were valid. This is fine but for extrapolation where I need to know the age of the position and velocity vectors to be able to use EPIC. I think that It would make sense to be able to lookup past states at a particular game tick (a synchronised concept of time) so should I implement this within the replication system, so the networking layer has its packet sequence number and the replication also sends the game tick with the replicated data on top of that protocol?
Unreal handles player movement separately from the rest of its replication using RPC. See this section:
http://udn.epicgames.com/Three/NetworkingOverview.html#Player Movement and Prediction Let me add some explanation as to why I appear to be so concerned with premature optimisation. I aim at sixty frames per second game frame rate. That leaves 16ms for all processes to execute in. Assuming 1ms is used for the render pipeline on average, that leaves 15ms. That's a lot of time if you write good code, and typically you'll have a fraction of a ms per client. However, this scales geometrically (I believe) with connection of new game-observing clients, as they have to be sent all other actors. Therefore .2 ms may seem small, but when that starts growing with just the scraper logic that seems dangerous. This said, these numbers are merely demonstrating the idea and are not representative of the actual model and this is without relevancy checks.
This is why you need to be conservative in determining which actors in a game need to be replicated and how often they need to be replicated.
Seeing as you mentioned your own progress, do you allow any non-actor classes to use replication? or have them handle their own data (e.g the scoreboard, clock)
In Unreal, the score board would be send to the client in WorldInfo which is a special actor representing the game world. You could also simply not use replication for things like that.
Right now I have 3 modes of communication in my game:
Normal replication happens only between actors and 5 times per second. This is done reliably, but order is not guaranteed and older packets can be ignored by the client. Example:
public override void Serialize(DeltaSerializer s, IReplicaClient destination)
{
base.Serialize(s, destination);
s.Write(_collideTiles);
s.Write(_collideActors);
s.Write(_blockActors);
s.Write(_layer);
}
public override void Deserialize(DeltaSerializer s, IReplicaClient source)
{
base.Deserialize(s, source);
s.ReadBoolean(ref _collideTiles);
s.ReadBoolean(ref _collideActors);
s.ReadBoolean(ref _blockActors);
s.ReadSByte(ref _layer);
}
Event messages can be sent manually between actors, which is what I use for my complex things like player movement or updating the inventory of an actor. For movement, this is done for every game update, which means 30 times per second as opposed to 5 for normal replication.
private void MoveAutonomous(Vector2 delta)
{
// Only call this on the client when it is autonomous
Debug.Assert(Actor.Role == NetRole.Autonomous);
Move(delta);
Vector2 newPos = Actor.Position;
// Save moves so we can replay them later if the server corrects us
_savedMoves.AddLast(new SavedMove(delta, _time));
// Tell the server to do the same move and confirm or correct our own
NetOutgoingMessage message = CreateEventMessage(EventServerMove);
message.Write(delta);
message.Write(newPos);
message.Write(_time);
message.Write((byte)_direction);
SendEvent(message, NetDeliveryMethod.UnreliableSequenced);
}
Player messages can be sent through through the player objects that represent clients in a game. The client only has its own local player object that can send to the server, but the server has one for each player logged in the game to communicate with its local counterpart.
My final question so far is should the server store the state of all actors every tick? I cannot think immediately of why it would save for replaying, but does Unreal store the "state" of each actor in a lookup by game time? And if so, is it every game tick or every network tick? It seems now would be the time to think about how that would be done, not further down the line.
And thanks for the example source, I'm sure it will be very useful!!
For each combination of a client and an actor relevant to it Unreal stores the values previously sent to that client. Replication is done by comparing the current value in an actor to the last sent value for each connection. This happens during network ticks only.