Variables
NetworkedObject
In a scene, each GameObject is assiotiated to a connected client. When many players join a scene, all GameObjects are distributed to them and redistributed if a player joins or leaves.
To share a GameObject, append a NetworkedObject
behaviour to it. You can share variables, events or spawners in your own behaviours after that.
If you check Associated
, objects will be duplicated on each client and each client will always manages its objects. (typically used on player character)
Variable
Share a value on the network. The value type can be a primitive value or a class. You can share complexe classes with arrays, dictionaries or other classes.
Initialize a float
Variable<float> _testA;
void Awake() {
_testA = this.NetVar<float>();
}
Change value and update it
_testA.Value = 4.2f; // thats it
Events
_testA.OnHandle += newValue => {}; // On value updated (receive from server)
_testA.OnEmit += newValue => {}; // On value updated (is emitter)
_testA.OnUpdate += newValue => {}; // On value updated (always)
_testA.OnNetworkInit += () => {}; // When this variable become shared on network. (IsNetworked becomes true)
Use getter
_testA.GetterValue = true;
Now, the value uses a lambda to send its value. The value is not sent immediatly, so with this conf, the value sent will always be the last set. (but it is a little more heavy to run)
Priority Changes batch priority
_testA.Priority = PacketsBatcher.Priority.immediate;
Status
_testA.IsNetworked // client is connected and this variable is shared
_testA.IsEmitter // true if this client is the emitter of this variable
_testA.IsActive // !IsNetworked || IsEmitter
This example moves randomly an object on x.
using EODE.Wonderland.SimpleNet;
[RequireComponent(typeof(NetworkedObject))]
public class TestScript : MonoBehaviour {
Variable<float> _testA;
void Awake() {
_testA = this.NetVar<float>();
}
void Start() {
StartCoroutine(TestRoutine());
}
IEnumerator TestRoutine() {
while (true) {
_testA.Value = Random.Range(-4f, 4f);
yield return new WaitForSeconds(1f);
}
}
void Update() {
transform.position = Vector3.Lerp(transform.position, new Vector3(_testA.Value, transform.position.y, transform.position.z), 0.01f);
}
}
Event
Event allows you to trigger events on all players.
NetEvent _testB;
void Awake() {
_testB = this.NetEvent();
_testB.OnCall += delay => {
Debug.Log("Call with delay = " + delay);
};
}
void Update() {
if (_testB.IsActive) {
if (Input.GetKeyDown(KeyCode.Keypad0)) {
_testB.Launch(); // trigger event
}
if (Input.GetKeyDown(KeyCode.Keypad1)) {
_testB.Launch(1f); // 1 sec delay
}
if (Input.GetKeyDown(KeyCode.Keypad2)) {
_testB.Launch(2f); // 2 sec delay
}
if (Input.GetKeyDown(KeyCode.Keypad3)) {
_testB.Launch(3f); // 3 sec delay
}
}
}
Delay is updated to try to trigger events at same time on all clients. For example, if client1 has 0.02s delay with the server and client2 has 0.03s; if client1 sends and waits 1s to trigger the event locally, client2 waits 0.95s.
Syncronizer
NetSyncVector2
and NetSyncVector3
includes a synchronizer to manage movements with predictions.
Very simple example of a controlled object with kayboard arrows
using EODE.Wonderland.SimpleNet;
using UnityEngine;
using SynchedVector3 = EODE.Wonderland.Net.SynchedVector3;
[RequireComponent(typeof(NetworkedObject))]
public class SimpleNetTestSync : MonoBehaviour {
public float Speed = 5f;
NetSyncVector3 _sync = new NetSyncVector3();
void Awake() {
_sync.Init(this, transform.position);
}
void Update() {
if (_sync.IsActive) {
var axis = GetAxis();
if (_prevAxis != axis) {
_prevAxis = axis;
_sync.Move(new Vector3(axis.x, 0f, axis.y));
}
}
transform.localPosition = _sync.Value;
_sync.Rotate(transform);
}
public Vector2 GetAxis() {
Vector2 axis = new Vector2(
(Input.GetKey(KeyCode.RightArrow) ? 1f : 0f) + (Input.GetKey(KeyCode.LeftArrow) ? -1f : 0f),
(Input.GetKey(KeyCode.UpArrow) ? 1f : 0f) + (Input.GetKey(KeyCode.DownArrow) ? -1f : 0f)
);
if (Mathf.Abs(axis.x) + Mathf.Abs(axis.y) > 1f) {
axis.x *= 0.68f;
axis.y *= 0.68f;
}
return axis * Speed;
}
Vector2 _prevAxis = Vector2.zero;
}