If you have 100’s of Mono behaviour scripts and if you want all of these scripts to run at the same interval
One of the solutions you would do so is to add the following code to all the Mono behaviour scripts.
void Update
{
time = time + Time.deltaTime;
if(time>Interval)
{
// your code
time = 0;
}
}
where you maintain the interval as a static variable in the master data or in a scriptable object and give reference to this in all the scripts to centralize your updates and repeat this code in every script
I do propose another way to do this using scriptable objects where you only need to use the above script once
Let’s analyze what behavior should a mono behaviour script that updates should have
1)It should have an update function.
2)It should have a fixed update function.
3)It should have a late update function.
It’s not like all mono behaviour scripts need all 3 types of updates
We also need some variable that tells which update function the script needs
So based on this lets make a interface called IUpdateable
public interface IUpdateable
{
public int UpdateMask
{
get;
}
void update();
void fixedUpdate();
void lateUpdate();
}
To check what types of update function needs to be implemented, we are gonna use a property called
update mask where
if first bit is on it means it needs update
if second bit is on it means it needs fixedupdate
if third bit is on it means it needs lateupdate
Based on above data we set the respective bits to true
Here in the code we check if the derived class overrides the function of parent class and set those overrides function to true
Now Let’s make the abstract class that implements IUpdateable and inherits from mono behaviour
public abstract class UpdateableMonoBehaviour : MonoBehaviour, IUpdateable
{
#region Fields
[SerializeField] protected UpdateV2 updater;
#endregion Fields
#region Properties
public virtual int UpdateMask
{
get
{
int _updateMask = 0;
if(this.GetType().GetMethod("update").DeclaringType == this.GetType())
_updateMask = _updateMask.setBitOn(0);
if (this.GetType().GetMethod("fixedUpdate").DeclaringType == this.GetType())
_updateMask = _updateMask.setBitOn(1);
if (this.GetType().GetMethod("lateUpdate").DeclaringType == this.GetType())
_updateMask = _updateMask.setBitOn(2);
return _updateMask;
}
}
#endregion Properties
#region Methods
protected void OnEnable() {
if(updater!=null)
updater.AddUpdateable(this);
}
protected void OnDisable() {
if (updater != null)
updater.RemoveUpdateable(this);
}
public virtual void finalUpdate()
{
}
public virtual void fixedUpdate()
{
}
public virtual void lateUpdate()
{
}
public virtual void update()
{
}
#endregion Methods
#region Helpers
#endregion Helpers
}
We also add onEnable and onDisable functions to subscribe/unsubscribe itself to scriptable object container
We also added a virtual update method for each type if we need a specific update type we override that update function
Now let’s make the scriptable object to store these objects
[CreateAssetMenu(menuName = "MyScriptable/UpdateV2")]
public class UpdateV2 : ScriptableObject
{
#region fields
private readonly List<IUpdateable> _updateList = new List<IUpdateable>();
private readonly List<IUpdateable> _fixedUpdateList = new List<IUpdateable>();
private readonly List<IUpdateable> _lateUpdateList = new List<IUpdateable>();
[SerializeField] float _updateTime = 1000;
[SerializeField] float _fixedTime = 1000;
[SerializeField] float _lateTime = 1000;
#endregion fields
#region properties
public float UpdateTime { get { return _updateTime; }}
public float FixedTime { get { return _fixedTime; }}
public float LateTime { get { return _lateTime; }}
#endregion properties
#region methods
public void AddUpdateable(IUpdateable updateable)
{
if(updateable.UpdateMask.checkIfBitIsOn(0))
{
if(!_updateList.Contains(updateable))
_updateList.Add(updateable);
}
if(updateable.UpdateMask.checkIfBitIsOn(1))
{
if(!_fixedUpdateList.Contains(updateable))
_fixedUpdateList.Add(updateable);
}
if(updateable.UpdateMask.checkIfBitIsOn(2))
{
if(!_lateUpdateList.Contains(updateable))
_lateUpdateList.Add(updateable);
}
}
public void RemoveUpdateable(IUpdateable updateable)
{
if (updateable.UpdateMask.checkIfBitIsOn(0))
{
if (_updateList.Contains(updateable))
_updateList.Remove(updateable);
}
if (updateable.UpdateMask.checkIfBitIsOn(1))
{
if (_fixedUpdateList.Contains(updateable))
_fixedUpdateList.Remove(updateable);
}
if (updateable.UpdateMask.checkIfBitIsOn(2))
{
if (_lateUpdateList.Contains(updateable))
_lateUpdateList.Remove(updateable);
}
}
public void update()
{
if(_updateList.Count!=0)
for (int i = _updateList.Count - 1; i >= 0; i--) { _updateList[i].update(); }
}
public void fixedUpdate()
{
if (_fixedUpdateList.Count != 0)
{
for (int i = _updateList.Count - 1; i >= 0; i--) { _fixedUpdateList[i].update(); }
}
}
public void lateUpdate()
{
if (_lateUpdateList.Count != 0)
for (int i = _updateList.Count - 1; i >= 0; i--) { _lateUpdateList[i].update(); }
}
#endregion methods
}
here we just make a data container to store all the IUpdateable objects.We create 3 lists for an update, a fixed update, a late update respectively.and a function to add and remove IUpdateable objects . In this functions we check if a specific bit is on or not and add them to specific lists.We also declare at what interval should it update for each update functions. We also define 3 functions to loop through each updates
Lets create a MonoBehaviour script to update our update functions
public class updaterScript : MonoBehaviour
{
// Start is called before the first frame update
[SerializeField] UpdateV2 updater;
float time = 0;
[SerializeField]float updateTime = 1000;
[SerializeField]float fixedTime = 1000;
[SerializeField]float lateTime = 1000;
void Start()
{
}
// Update is called once per frame
void Update()
{
time = time + Time.deltaTime;
if(time>updater.UpdateTime)
{
if(updater != null)
updater.update();
time = 0;
}
}
void FixedUpdate()
{
time = time + Time.deltaTime;
if (time > updater.FixedTime)
{
if (updater != null)
updater.fixedUpdate();
time = 0;
}
}
private void LateUpdate()
{
time = time + Time.deltaTime;
if (time > updater.LateTime)
{
if (updater != null)
updater.lateUpdate();
time = 0;
}
}
Lets make script that inherits from UpdateableMonoBehaviour that meows every 1000 frames
public class Meower : UpdateableMonoBehaviour
{
private new void OnEnable()
{
base.OnEnable();
Debug.Log("lol");
}
// Update is called once per frame
public override void update()
{
Debug.Log("meow");
}
}
I am still a beginner learning new things so if I have made any mistakes or any improvements or new way of doing it . Please point it out
That’s it for today
May the code be with you
kuro out
Reference
1 - Efficient Updating - Take Control of Update Functions