I am trying to create a system for daily events in Unity, but I am facing an obstacle where performance and memory are very sensitive for me,The DailyEvent consists of a list of DailyEventAction, which hold the data of the actions to be invoked, such as the name, time, and a reference to the action function.
and I am using Action for each DailyEventAction as the reference for the procedure to be followed to execute the desired event when its time comes.
What I want is a way to assign the Action and pass the function parameter ExecuteEvent(NightLightsEvent eventData) without creating a closure.
Because the list may contain a large number of DailyEventAction, thus more memory will be consumed when creating a closure for each DailyEventAction in the list.
NightLightsManager script: This script is an example of creating an action for any daily event.
using System.Collections.Generic;
using UnityEngine;
public class NightLightsManager : DailyEvent
{
public override List<DailyEventAction> DailyEventActions { get; protected set; } = new List<DailyEventAction>();
DailyEventAction _dailyEventActionToAdd = new DailyEventAction();
[SerializeField] private List<NightLightsEvent> _nightLightsEvents;
[SerializeField] private Light[] _streetLights;
void Init()
{
if (_nightLightsEvents.Count < 1)
return;
NightLightsEvent nightLightsEvent = new NightLightsEvent();
_nightLightsEvents.Sort();
for (int i = 0; i < _nightLightsEvents.Count; i++)
{
if (DailyEventActions.FindIndex(localDailyEvntAction => localDailyEvntAction.Name == _nightLightsEvents[i].Name) < 0)
{
int currentIndex = i;
_dailyEventActionToAdd.DailyEvent = this;
_dailyEventActionToAdd.Name = _nightLightsEvents[i].Name;
nightLightsEvent = _nightLightsEvents[currentIndex];
_dailyEventActionToAdd.Action = () => ExecuteEvent(nightLightsEvent);
_dailyEventActionToAdd.TimeInMinutes = _nightLightsEvents[i].Hour * 60 + _nightLightsEvents[i].Minute;
DailyEventActions.Add(_dailyEventActionToAdd);
}
}
}
void ExecuteEvent(NightLightsEvent eventData)
{
for (int i = 0; i < _streetLights.Length; i++)
{
_streetLights[i].enabled = eventData.IsLightsOn;
}
Debug.Log($"Invoking {eventData.Name} | {eventData.IsLightsOn} lights at: {TimeManager.Instance.CurrentTotalMinutes}");
}
}
DailyEventAction script: It holds the data of the action to be invoke, such as the name, time, and a reference to the action function.
using UnityEngine;
using System;
[Serializable]
public struct DailyEventAction : IComparable<DailyEventAction>
{
public DailyEvent DailyEvent;
public string Name;
public Action Action;
[SerializeField, Range(0, 1439)] private int _timeInMinutes;
public int TimeInMinutes
{
get => _timeInMinutes;
set => _timeInMinutes = Mathf.Clamp(value, 0, 1439);
}
public DailyEventAction(DailyEvent dailyEvent, string name, Action action, int hour, int minute)
{
DailyEvent = dailyEvent;
Name = name;
Action = action;
_timeInMinutes = Mathf.Clamp(hour, 0, 23) * 60 + Mathf.Clamp(minute, 0, 59);
}
public DailyEventAction(DailyEvent dailyEvent, string name, Action action, int timeInMinutes)
{
DailyEvent = dailyEvent;
Name = name;
Action = action;
_timeInMinutes = timeInMinutes;
}
public int CompareTo(DailyEventAction other)
{
return TimeInMinutes - other.TimeInMinutes;
}
}
NightLightsEvent script: It holds the data that will be used as a parameter in the function and executes the function based on it.
using UnityEngine;
using System;
[Serializable]
public struct NightLightsEvent : IComparable<NightLightsEvent>
{
public string Name;
[SerializeField, Range(0, 23)]
private int _hour;
public int Hour
{
get => _hour;
set => _hour = Mathf.Clamp(value, 0, 23);
}
[SerializeField, Range(0, 59)]
private int _minute;
public int Minute
{
get => _minute;
set => _minute = Mathf.Clamp(value, 0, 59);
}
public bool IsLightsOn;
public NightLightsEvent(string name, int hour, int minute, bool isLightsOn)
{
Name = name;
_hour = Mathf.Clamp(hour, 0, 23);
_minute = Mathf.Clamp(minute, 0, 59);
IsLightsOn = isLightsOn;
}
public int CompareTo(NightLightsEvent other)
{
return (Hour * 60 + Minute) - (other.Hour * 60 + other.Minute);
}
}