SyncVar/Field Change Events
This PR enables on-change callbacks for value-type SyncVar<> fields by allowing users to specify a callback method name via [SyncVarFlags("CallbackName")]. Whenever a SyncVar<> changes.
Additionally, custom sync fields (e.g., SyncString, SyncNetSerializable<T>) now support a ValueChanged event, letting developers subscribe to any changes.
Unfortunately, SyncVar Value Types and SyncFields must be handled differently.
Example:
using LiteEntitySystem;
using LiteEntitySystem.Internal;
using UnityEngine;
[EntityFlags(EntityFlags.UpdateOnClient)]
public class TestEntity : EntityLogic
{
// A simple SyncVar<int> with an on-change callback
[SyncVarFlags("OnCounterChanged")]
private SyncVar<int> _counter;
// A SyncVar<bool> with another callback
[SyncVarFlags("OnToggle")]
private SyncVar<bool> _toggle;
// A custom sync field (e.g., SyncString) that raises a ValueChanged event
private readonly SyncString _greeting = new();
// Normal constructor
public TestEntity(EntityParams entityParams) : base(entityParams) {}
// Called when `_counter` changes
private void OnCounterChanged(int newValue)
{
if (IsClient)
Debug.Log("Counter changed to: " + newValue);
}
// Called when `_toggle` changes
private void OnToggle(bool state)
{
if (IsClient)
Debug.Log("Toggle state changed: " + state);
}
// Example usage of SyncString's event
private void OnGreetingValueChanged(string oldValue, string newValue)
{
if (IsClient)
Debug.Log($"Greeting changed from '{oldValue}' to '{newValue}'");
}
protected override void OnConstructed()
{
base.OnConstructed();
// Subscribe to the SyncString's ValueChanged event
_greeting.ValueChanged += OnGreetingValueChanged;
if (IsServer)
{
// You can initialize values on the server
_counter.Value = 1;
_greeting.Value = "Hello from the server!";
}
}
private float _elapsedTime;
protected override void Update()
{
if (IsServer)
{
// Increment `_counter` and flip `_toggle` every 2 seconds
_elapsedTime += Time.deltaTime;
if (_elapsedTime >= 2f)
{
_counter.Value += 1;
_toggle.Value = !_toggle.Value;
// Also update the greeting
_greeting.Value = "Server greeting " + _counter.Value;
_elapsedTime = 0f;
}
}
}
}
@RevenantX would do you thinks about this? I know that you can subscribe with bind to value type changes, but I tried to make it easier for devs. For Sync Fields I coudn't find a way for change notifications in the current codebase.
@ltwlf i use BindOnChange because it work for IL2CPP (and possibly for some AOT things in future) inside Unity. IL2CPP need to know all generic types that will be used in resulting code. And methods that called by reflection without direct call can be stripped from resulting executable
https://docs.unity3d.com/6000.0/Documentation/Manual/scripting-backends-il2cpp.html