当前位置:网站首页>Mlapi series - 04 - network variables and network serialization [network synchronization]
Mlapi series - 04 - network variables and network serialization [network synchronization]
2022-07-06 04:08:00 【Feilang era [fwc – fe]】
MLAPI series - 04 - Network variables and network serialization 【 Network synchronization 】
- One 、 Overview of network synchronization
- Two 、 Network variables
- 3、 ... and 、 About framework built-in serialization
- Four 、 Network variables use
- 5、 ... and 、 MLAPI pre-10 Some changes in the version
One 、 Overview of network synchronization
Netcode There are two main means of network synchronization : The first is the RPC Mechanism , The remote invocation , The second is to use network variables .
Two 、 Network variables
Network variables belong to Netcode Unique network type , Package maintenance one Value, If you want to encapsulate multiple fields or arrays, you need to encapsulate them yourself .
3、 ... and 、 About framework built-in serialization
1 Network variables are defined as generic classes
NetworkVariable, Support C# Basic types 、Unity Basic types 、 Custom enumeration .2 RPC Pass message parameters , You need to use serializable types , The following serializable types and inherited serialization interfaces are supported
INetworkSerializableCustom serialization type of .
1 C# The base type
C# The base type will be serialized by the built-in serialization code .
These types include :bool, char, sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and string.
[ServerRpc]
void FooServerRpc(int somenumber, string sometext) {
/* ... */ }
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
// Client -> Server
FooServerRpc(Time.frameCount, "hello, world");
}
}
2 Unity The base type
Unity The base type Color, Color32, Vector2, Vector3, Vector4, Quaternion, Ray, Ray2D The type will be serialized by the built-in serialization code .
[ClientRpc]
void BarClientRpc(Color somecolor) {
/* ... */ }
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
BarClientRpc(Color.red); // Server -> Client
}
}
3 Enumeration type
User defined enumeration types will be serialized by built-in serialization code ( Use the base integer type )
enum SmallEnum : byte // 0-255 Limited length
{
A,
B,
C
}
enum NormalEnum // default -> int
{
X,
Y,
Z
}
[ServerRpc]
void ConfigServerRpc(SmallEnum smallEnum, NormalEnum normalEnum)
{
/* ... */ }
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
ConfigServerRpc(SmallEnum.A, NormalEnum.X); // Client -> Server
}
}
4 Array
image int[] Such an array Serialized by built-in serialization code :
If their base type is one of the types that support serialization ( Such as Vector3) perhaps Whether they realize INetworkSerializable Interface .
[ServerRpc]
void HelloServerRpc(int[] scores, Color[] colors) {
/* ... */ }
[ClientRpc]
void WorldClientRpc(MyComplexType[] values) {
/* ... */ }
5 INetworkSerializable Interface
INetworkSerializable Interface can be used to define custom serializable types .
struct MyComplexStruct : INetworkSerializable
{
public Vector3 Position;
public Quaternion Rotation;
// INetworkSerializable
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref Position);
serializer.SerializeValue(ref Rotation);
}
// ~INetworkSerializable
}
// Implementation types INetworkSerializable, And be NetworkSerializer, RPCs and NetworkVariable Support
[ServerRpc]
void MyServerRpc(MyComplexStruct myStruct) {
/* ... */ }
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
MyServerRpc(
new MyComplexStruct
{
Position = transform.position,
Rotation = transform.rotation
}); // Client -> Server
}
}
5.1 Nested sequence type
Nested sequence types will be null Unless you initialize in one of the following ways :
- Manually before calling SerializeValue If serializer.IsReader( Or something like that )
- Initialize in the default constructor
This is intentional . Before initializing correctly , You may see that these values are null. The serializer did not deserialize them , therefore null Values are simply applied before serialization .
5.2 Conditional serialization
Because there is more control over the serialization of structures , So you can implement conditional serialization at run time .
Example : Array
public struct MyCustomStruct : INetworkSerializable
{
public int[] Array;
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
// Length
int length = 0;
if (!serializer.IsReader)
{
length = Array.Length;
}
serializer.SerializeValue(ref length);
// Array
if (serializer.IsReader)
{
Array = new int[length];
}
for (int n = 0; n < length; ++n)
{
serializer.SerializeValue(ref Array[n]);
}
}
}
Read :
serialize ( Deserialization )length Flow back from
iteration Array member n=length times Serialize the value ( Deserialization ) Back to array [n] Elements in the streamwrite in :
Serialization length = Array Length of the write stream
Iterate over array members n = Length times Serialize the values in the array [n] Element is added to the stream
this BufferSerializer.IsReader Flags are used here to determine whether to set length value , Then we use it to determine whether to create a new int[] Examples and length Size to set Array Before reading the value from the stream .
There is another equivalent but opposite BufferSerializer.IsWriting
Example : Move
public struct MyMoveStruct : INetworkSerializable
{
public Vector3 Position;
public Quaternion Rotation;
public bool SyncVelocity;
public Vector3 LinearVelocity;
public Vector3 AngularVelocity;
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
// Position & Rotation
serializer.SerializeValue(ref Position);
serializer.SerializeValue(ref Rotation);
// LinearVelocity & AngularVelocity
serializer.SerializeValue(ref SyncVelocity);
if (SyncVelocity)
{
serializer.SerializeValue(ref LinearVelocity);
serializer.SerializeValue(ref AngularVelocity);
}
}
}
Read :
serialize ( Deserialization )Position Flow back from
serialize ( Deserialization )Rotation Flow back from
serialize ( Deserialization )SyncVelocity Flow back from
Check whether the SyncVelocity Set to true, If so :
serialize ( Deserialization )LinearVelocity Flow back from
serialize ( Deserialization )AngularVelocity Flow back from
write in :
load Position Into the stream
load Rotation Into the stream
load SyncVelocity Into the stream
Check whether the SyncVelocity Set to true, If so :
load LinearVelocity Into the stream
load AngularVelocity Into the stream
Different from the arrangement in the above example , We didn't use BufferSerializer.IsReader Flag to change the serialization logic , But change the value of the serialization flag itself .If SyncVelocity Flag set to true , be LinearVelocity and AngularVelocity Will be serialized into the stream
When SyncVelocity Flag set to false, We will leave LinearVelocity and AngularVelocity Use the default value .
5.3 Recursive nested serialization
Nested members can be serialized recursively INetworkSerializable Interfaces in the hierarchical tree .
Example :
public struct MyStructA : INetworkSerializable
{
public Vector3 Position;
public Quaternion Rotation;
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref Position);
serializer.SerializeValue(ref Rotation);
}
}
public struct MyStructB : INetworkSerializable
{
public int SomeNumber;
public string SomeText;
public MyStructA StructA;
void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref SomeNumber);
serializer.SerializeValue(ref SomeText);
StructA.NetworkSerialize(serializer);
}
}
If we want to load separately MyStructA, It will use NetworkSerializer load Position and Rotation Inflow ,.
However , If we want to serialize MyStructB, It serializes SomeNumber and SomeText Into the stream , Then serialize StructA adopt Call -
MyStructA void
NetworkSerialize(NetworkSerializer) Method , This method serializes Position and Rotation Enter the same first-class .
Be careful
Technically speaking , There is no hard limit to the number INetworkSerializable Fields that can be serialized along the tree hierarchy . In practice , Consider memory and bandwidth boundaries for best performance .
You can conditionally serialize in a recursive nested serialization scenario , And use these two functions .
6 Custom Serialization
When using RPCs,NetworkVariable Or any other game object network code that needs to be serialized (Netcode) Related tasks .Netcode Use the default serialization pipeline , As shown below :
Custom Types => Built In Types => INetworkSerializable
in other words , When Netcode The first time you get a type , It will check any custom types that the user has registered for serialization , Then it will check whether it is a built-in type , Such as Vector3、float etc. . These are handled by default . If not , It will check whether the type inherits INetworkSerializable If there is , It will call its write Method .
By default , Any satisfaction unmanaged Generic constraints can be automatically serialized as RPC Parameters . This includes all basic types (bool、byte、int、float、enum etc. ) And any structure that contains only these basic types .
Through this process , You can override all serialization types , Even built into types , And use the provided API, It can even be done with types that you don't define yourself , Those types behind the third-party wall , for example . Network type .
To register a custom type or override a processed type , Need to be for FastBufferReader.ReadValueSafe() and FastBufferWriter.WriteValueSafe():
// tell Netcode How to serialize and deserialize in the future Url.
// The class name doesn't matter here .
public static class SerializationExtensions
{
public static void ReadValueSafe(this FastBufferReader reader, out Url value)
{
reader.ReadValueSafe(out string val);
value = new Url(val);
}
public static void WriteValueSafe(this FastBufferWriter writer, in Url value)
{
writer.WriteValueSafe(instance.Value);
}
}
RPC The code generation of will be directly through FastBufferWriter and FastBufferReader Get and use these functions automatically .
You can also choose to use the same method to add pairs BufferSerializer<TReaderWriter>.SerializeValue(), If you will , This will make this type in INetworkSerializable type :
// The class name doesn't matter here .
public static class SerializationExtensions
{
public static void SerializeValue<TReaderWriter>(this BufferSerializer<TReaderWriter> serializer, ref Url value) where TReaderWriter: IReaderWriter
{
if (serializer.IsReader)
{
value = new Url();
}
serializer.SerializeValue(ref value.Value);
}
}
7 Network objects and network behavior
GameObjects, NetworkObjects and NetworkBehaviour Not a serializable type , So it can't be in RPC perhaps NetworkVariables By default .
There are two convenient wrappers【 Wrappers 】 Can be used to send pairs NetworkObject Or a NetworkBehaviour adopt RPC or NetworkVariables.
7.1 NetworkObjectReference Network object reference type
NetworkObjectReference Can be used to serialize pairs NetworkObject. It can only be used on already generated NetworkObjects.
Here is a use NetworkObject Reference of sending target NetworkObject adopt RPC:
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
var targetObject = target.GetComponent<NetworkObject>();
ShootTargetServerRpc(targetObject);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkObjectReference target)
{
if (target.TryGet(out NetworkObject targetObject))
{
// deal damage or something to target object.
}
else
{
// Target not found on server, likely because it already has been destroyed/despawned.
}
}
}
7.2 Implicit Operators Implicit operation
And from / Implicit operator to transform NetworkObject/GameObject This can be used to simplify code . for example , The above example can also be written in the following way :
NetworkObjectReference -> NetworkObject
GameObject -> NetworkObjectReference
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
ShootTargetServerRpc(target);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkObjectReference target)
{
NetworkObject targetObject = target;
}
}
Be careful : If the reference is not found , To
NetworkObject/GameObjectThe implicit conversion of will result in Null.
7.3 NetworkBehaviourReference Network behavior reference
NetworkBehaviourReference Work in a way similar to NetworkObjectReference It is used to refer to specific NetworkBehaviour Derived components on NetworkObject.
public class Health : NetworkBehaviour
{
public NetworkVariable<int> Health = new NetworkVariable<int>();
}
public class Weapon : NetworkBehaviour
{
public void ShootTarget(GameObject target)
{
var health = target.GetComponent<Health>();
ShootTargetServerRpc(health, 10);
}
[ServerRpc]
public void ShootTargetServerRpc(NetworkBehaviourReference health, int damage)
{
if (health.TryGet(out Health healthComponent))
{
healthComponent.Health.Value -= damage;
}
}
}
7.4 Network object reference 、 How network behavior references work
NetworkObjectReference and NetworkBehaviourReference It's convenient wrappers Wrappers , It serializes NetworkObject When sending , Retrieve the corresponding Use that id.NetworkBehaviourReference Send an additional index , Used to find the correct NetworkBehaviour In which NetworkObject On .
They all achieve INetworkSerializable Interface .
Four 、 Network variables use
Network variable generic class NetworkVariable, Support C# Basic types and Unity Basic types .
1 bool Network variables of type use
When NetworkVariable<T> Of Value change , OnValueChanged Callback the parameter with old and new values , The callback function should constantly poll for the latest value in response to value changes .
public class Door : NetworkBehaviour
{
public NetworkVariable<bool> State = new NetworkVariable<bool>();
public override void OnNetworkSpawn()
{
State.OnValueChanged += OnStateChanged;
}
public override void OnNetworkDespawn()
{
State.OnValueChanged -= OnStateChanged;
}
public void OnStateChanged(bool previous, bool current)
{
// note: `State.Value` will be equal to `current` here
if (State.Value)
{
// door is open:
// - rotate door transform
// - play animations, sound etc.
}
else
{
// door is closed:
// - rotate door transform
// - play animations, sound etc.
}
}
[ServerRpc(RequireOwnership = false)]
public void ToggleServerRpc()
{
// this will cause a replication over the network
// and ultimately invoke `OnValueChanged` on receivers
State.Value = !State.Value;
}
}
2 Read and write permissions of network variables
By default ,NetworkVariable<T> It can only be written by the server and can be read by anyone . These permissions can be changed through the constructor .
// A snippet from the Netcode SDK
public abstract class NetworkVariableBase
{
// ...
public const NetworkVariableReadPermission DefaultReadPerm =
NetworkVariableReadPermission.Everyone;
public const NetworkVariableWritePermission DefaultWritePerm =
NetworkVariableWritePermission.Server;
// ...
}
public class NetworkVariable<T> : NetworkVariableBase
{
// ...
public NetworkVariable(T value = default,
NetworkVariableReadPermission readPerm = DefaultReadPerm,
NetworkVariableWritePermission writePerm = DefaultWritePerm)
{
// ...
}
// ...
}
2.1 Read
public enum NetworkVariableReadPermission
{
Everyone,
Owner
}
Everyone → All clients and server will get value updates.
Owner → Only server and the owner client will get value updates.
2.2 Write
public enum NetworkVariableWritePermission
{
Server,
Owner
}
Server → Only the server can write to the value.
Owner → Only the owner client can write to the value, server can’t write to the value.
3. Sample code integration
public class Cube : NetworkBehaviour
{
// everyone can read, only owner can write
public NetworkVariable<Vector3> NetPosition = new NetworkVariable<Vector3>(
default,
NetworkVariableBase.DefaultReadPerm, // Everyone
NetworkVariableWritePermission.Owner);
private void FixedUpdate()
{
// owner writes, others read & apply
if (IsOwner)
{
NetPosition.Value = transform.position;
}
else
{
transform.position = NetPosition.Value;
}
}
// everyone can read, only server can write
public NetworkVariable<Color> NetColor = new NetworkVariable<Color>(
default,
NetworkVariableBase.DefaultReadPerm, // Everyone
NetworkVariableWritePermission.Server);
public override void OnNetworkSpawn()
{
NetColor.OnValueChanged += OnColorChanged;
}
public override void OnNetworkDespawn()
{
NetColor.OnValueChanged -= OnColorChanged;
}
public void OnColorChanged(Color previous, Color current)
{
// update materials etc.
}
[ServerRpc(RequireOwnership = false)]
public void ChangeColorServerRpc()
{
NetColor.Value = Random.ColorHSV();
}
}
5、 ... and 、 MLAPI pre-10 Some changes in the version
0.0 Upgrade instructions
lately Netcode The upgrade pre-10 edition , The official repaired some bug, Will the blogger provide from pre-6 Version of the custom generic network variable compilation caused the editor to crash bug Repair the , There are other changes .


1 Fix array generic crash
Fixed NetworkAnimator issue where it was not always disposing the NativeArray that is allocated when spawned. (#1946)

2 ClientNetworkTransform Base class function name OnIsServerAuthoritatitive change
Before the change :
// Overwrite this value and return false To follow the owner's permissions , otherwise , The default is server permission
protected override bool OnIsServerAuthoritatitive()
{
return false;
}
After modification :
// Overwrite this value and return false To follow the owner's permissions , otherwise , The default is server permission
protected override bool OnIsServerAuthoritative()
{
return false;
}
3 Base class changes :NetworkVariableSerialization It is amended as follows NetworkVariableBase
After upgrading , Partial inheritance NetworkVariableSerialization Of Custom network variable script There may be an error .
The reason for the error is that the base class used in the transition phase is used NetworkVariableSerialization May be ready to abandon .
3.1 Error reason
1 Before version upgrade , It belongs to excessive script , Same as network variables , Inherits the network variable base class
NetworkVariableBase, rewriteReadDeltaAnd other base class methods can use encapsulatedReadandWriteStatic methods
1.1 Easy to use
----------------------------------------------------------------------------------------【pre-9】
2 After version upgrade , Removed base class 、ReadandWriteStatic method, etc
2.1 The custom network variable returns to the base class of the network variableNetworkVariableBasethat will do
----------------------------------------------------------------------------------------【pre-10】
3.2 Example of script modification
Before modification :
Read(reader, out Value.Array[i]);
After the changes :
reader.ReadValueSafe(out Value.Array[i]);
边栏推荐
- Global and Chinese markets for patent hole oval devices 2022-2028: Research Report on technology, participants, trends, market size and share
- 深入浅出node模板解析错误escape is not a function
- Prime protocol announces cross chain interconnection applications on moonbeam
- Global and Chinese market of aircraft anti icing and rain protection systems 2022-2028: Research Report on technology, participants, trends, market size and share
- ESP32_ FreeRTOS_ Arduino_ 1_ Create task
- asp. Core is compatible with both JWT authentication and cookies authentication
- Record the pit of NETCORE's memory surge
- 1291_Xshell日志中增加时间戳的功能
- 10个 Istio 流量管理 最常用的例子,你知道几个?
- 图应用详解
猜你喜欢

Solution to the problem that the root account of MySQL database cannot be logged in remotely

Thread sleep, thread sleep application scenarios
![[Key shake elimination] development of key shake elimination module based on FPGA](/img/47/c3833c077ad89d4906e425ced945bb.png)
[Key shake elimination] development of key shake elimination module based on FPGA

Yyds dry goods inventory hcie security Day11: preliminary study of firewall dual machine hot standby and vgmp concepts

自动化测试的好处

ESP32(基于Arduino)连接EMQX的Mqtt服务器上传信息与命令控制

Facebook等大厂超十亿用户数据遭泄露,早该关注DID了
![Cf464e the classic problem [shortest path, chairman tree]](/img/6b/65b2dc62422a45cc72f287c38dbc58.jpg)
Cf464e the classic problem [shortest path, chairman tree]
![[adjustable delay network] development of FPGA based adjustable delay network system Verilog](/img/82/7ff7f99f5164f91fab7713978cf720.png)
[adjustable delay network] development of FPGA based adjustable delay network system Verilog

Le compte racine de la base de données MySQL ne peut pas se connecter à distance à la solution
随机推荐
10个 Istio 流量管理 最常用的例子,你知道几个?
Interface idempotency
Oracle ORA error message
Stc8h development (XII): I2C drive AT24C08, at24c32 series EEPROM storage
51nod 1130 n factorial length V2 (Stirling approximation)
阿里测试师用UI自动化测试实现元素定位
Use js to complete an LRU cache
Web components series (VII) -- life cycle of custom components
Basic knowledge of binary tree, BFC, DFS
C#(二十九)之C#listBox checkedlistbox imagelist
Take you to wechat applet development in 3 minutes
Ethernet port &arm & MOS &push-pull open drain &up and down &high and low sides &time domain and frequency domain Fourier
AcWing 243. A simple integer problem 2 (tree array interval modification interval query)
使用JS完成一个LRU缓存
Fundamentals of SQL database operation
/usr/bin/gzip: 1: ELF: not found/usr/bin/gzip: 3: : not found/usr/bin/gzip: 4: Syntax error:
MySQL transaction isolation level
Global and Chinese markets for fire resistant conveyor belts 2022-2028: Research Report on technology, participants, trends, market size and share
[FPGA tutorial case 12] design and implementation of complex multiplier based on vivado core
Global and Chinese market of rubber wheel wedges 2022-2028: Research Report on technology, participants, trends, market size and share

