Analysis of the core principles of state synchronization in online game development

State synchronization is a server/client synchronization technology that must be mastered in online games. What is state synchronization, and how is it implemented in the game? With these questions in mind, this article will give you a detailed analysis of state synchronization from the following three aspects.

What kind of games should use status synchronization

As long as it is an online game, any game that involves synchronization between the server and the client can use state synchronization. To give a few examples of state synchronization, such as “World of Warcraft”, Tencent’s “Chicken Eater”, “Auto Chess” and most other games. Multiplayer online online games are all made using state synchronization. In other words, except for Moba and FPS games where a few people play against each other (5v5, 10v10), which use frame synchronization, all other online games are state synchronized. For games like massive multiplayer games online at the same time, it can only be done using state synchronization. The current mainstream network synchronization methods are status synchronization and frame synchronization. Status synchronization can be used for any type of game, while frame synchronization can only be used by a few people in a game at the same time

Compared with state synchronization, frame synchronization only synchronizes user operations, and the client iteratively calculates all game logic. It is more like a stand-alone game, except that some player inputs come from the server. Frame synchronization is better than state synchronization in terms of operational feel and player response time. But it also has its problems, such as anti-cheating, disconnection and reconnection, which require quick iteration from scratch one frame at a time. This limits the types of games that frame synchronization can do, and it cannot do games where a large number of people are online at the same time or online for a long time. For example

How to run game logic on the server

public class PlayerEntity {
\t
@Protobuf(order = 1, required = true)
public StatusComponent statusInfo; // Player's status;
\t
@Protobuf(order = 2, required = true)
public AccountComponent accountInfo;
\t
@Protobuf(order = 3, required = true)
public GhostPlayerInfoComponent ghostInfo;
\t
@Protobuf(order = 4, required = true)
public EquipmentComponent equipmentInfo;
\t
@Protobuf(order = 5, required = true)
public TransformComponent transformInfo;
\t
// Player private data is unnecessary;
@Protobuf(order = 6, required = false)
public PrivatePlayerInfoComponent playerInfo;
\t
public AOIComponent aoiComponent;
public SkillBuffComponent skillBuffComponent;
\t
public AttackComponent attackComponent;
public ShapeComponent shapeInfo;
public AStarComponent astarComponent;
public JoystickComponent joystickComponent;
\t
public PlayerEntity() {
this.accountInfo = null;
this.playerInfo = null;
this.ghostInfo = null;
this.equipmentInfo = null;
this.shapeInfo = null;
this.transformInfo = null;
this.astarComponent = null;
this.joystickComponent = null;
this.attackComponent = null;
this.skillBuffComponent = null;
this.statusInfo = null;
}
\t
\t
public static PlayerEntity create(Player p) {
PlayerEntity entity = new PlayerEntity();
entity.statusInfo = new StatusComponent();
entity.statusInfo.state = RoleState.Idle;
\t\t
entity.accountInfo = new AccountComponent();
entity.playerInfo = new PrivatePlayerInfoComponent();
entity.ghostInfo = new GhostPlayerInfoComponent();
entity.equipmentInfo = new EquipmentComponent();
entity.shapeInfo = new ShapeComponent();
entity.transformInfo = new TransformComponent();
entity.aoiComponent = new AOIComponent();
\t\t
SkillBuffSystem.InitSkilBuffComponent(entity);
\t\t
entity.astarComponent = new AStarComponent();
entity.joystickComponent = new JoystickComponent();
entity.attackComponent = new AttackComponent();
\t\t
entity.statusInfo.entityId = p.getId();
LoginMgr.getInstance().loadAccountComponentFromAccountId(entity.accountInfo, p.getAccountId());
PlayerMgr.getInstance().loadPlayerEntityFromPlayer(entity, p);
PlayerMgr.getInstance().loadEquipMentComponentDataFromPlayer(entity.equipmentInfo, p);
\t\t
entity.shapeInfo.height = 2.0f;
entity.shapeInfo.R = 0.5f;
\t\t
\t\t
return entity;
}
\t
}

For example, the TransformComponent above describes the position and rotation of this game object in the world.

public class TransformComponent {
@Protobuf(order = 1, required = true)
public Vector3Component position;
\t
@Protobuf(order = 2, required = true)
public float eulerAngleY = 0;
\t
\t
public TransformComponent clone() {
TransformComponent t = new TransformComponent();
t.position = this.position.clone();
t.eulerAngleY = this.eulerAngleY;
return t;
}
\t
public void LookAt(Vector3Component point) {
Vector3Component src = this.position;
Vector3Component dir = Vector3Component.sub(point, src);
float degree = (float)(Math.atan2(dir.z, dir.x) * 180 / Math.PI);
degree = 360 - degree;
this.eulerAngleY = degree + 90;
}
}

Yes A little bit demanding. Make a map editor according to different types of games and use the most appropriate technology. At the same time, both the client and the server use this set. The client has a map editor tool to edit the map’s terrain + bake the map connection data. These data can be exported to the server in the corresponding format. The server uses these data to utilize the above Update to perform iterative calculation (the same as the Update iteration of client development).

How to synchronize the server and client

The game map is set up on the server, and under the iteration of the server update, each player data + NPC data is “run” on the server. The next step is how to synchronize with the client. Does status synchronization mean that if the location on the server changes, the location of the client must be synchronized again? In fact, it is not, or not entirely. We will describe important changes in the game as “status changes”. It is important for you to remember one thing about status synchronization: The server runs the server side, and the client runs the client side. Every time the status changes, it must be synchronized before processing.

Step1: When client player A clicks on the map with the mouse or touch, the destination map coordinates and operation events (type identifiers) are sent to the server.

Step2: The server receives this event and does a legality check (such as legality check of the operation, legality of the destination coordinate range). The player is at point A and navigates to point B thousands of miles away. If the distance is too far, there may be a plug-in. (suspicious), and then deal with it after passing the inspection.

Step5: The client receives the event that player A wants to walk to point P. For A, the status has changed. Synchronize first, synchronize the latest status information of player A on the server in the data packet, and then synchronize again. Perform local pathfinding and navigation to walk to point p, the client runs the client.

Step6: Player A on the server reaches the destination. At this time Player A’s status changes. The server sends this status event to all players who are interested in player A, including A himself.

Step7: After the client receives the status event that player A has arrived at the destination, it synchronizes the status information of player A on the server side in the data packet.

The conclusion drawn from the above is that there is no need to synchronize the position changes during walking to the client. The server runs the server side, and the client runs the client side. It is just that after important status changes, the server side synchronizes the latest The information is sent to the client, and the client synchronizes. In the above example, when the player is walking and the player performs other attack operations, the status changes again, and the server will process it again

Well, today’s status synchronization will be shared here. Follow us to learn more practical tutorials on online games.