I am trying to learn delegates and events.I want to get notified if a value changes in program so trying to write an customised event for it.I ran the below code but not working .
public delegate void TestDel();
public static event TestDel testevent;
int val = 0;
int temp = 0;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
public void ChangeValue()//Method for button click
{
temp = val;
val = 1;
if(temp!=val)
{
testevent += responsemethod;
}
}
private void OnDisable()
{
testevent -= responsemethod;
}
public void responsemethod()
{
Debug.Log("Value Changed");
}
Here, inside your button click listener, you are just adding the event handler to the event each time the button is clicked and the values are different. Instead, you should add it earlier (and just once) and in ChangeValue method just invoke the event.
void OnEnable()
{
testevent += responsemethod;
}
void OnDisable()
{
testevent -= responsemethod;
}
public void ChangeValue()
{
temp = val;
val = 1;
if(temp != val)
{
testevent.Invoke(); // or just testevent();
}
}
The event is registered via the += operator. So when the script is enabled, the event is registered. You ChangeValue method will fire the event when the temp does not equal the value - via the testevent.Invoke(). It is good practice to test the event before invoking.
Something like:
if(event != null)
event.invoke();
Or the shorthand:
event?.invoke();
Events are a way to have a pointer to a function, since gen 4 languages usually abstract out pointers.
public class MyStats
{
public delegate void OnStatChanged(); //EVENT TYPE FOR WHEN THE STAT CHANGES
public OnStatChanged OnValueChange; //AN 'INSTANCE' OF THE ONSTATCHANGED TYPE
private float _Value; //THE VALUE OF MYSTAT
public float Value //GET - SET
{
get { return _Value; } //RETURN THE VALUE OF MYSTAT
set //SET THE VALUE OF MYSTAT
{
_Value = value; //REPLACE MYSTAT VALUE WITH NEW VALUE
OnValueChange?.Invoke(); //IF ONVALUECHANGE POINTS TO A FUNCTION, CALL IT
//The above OnValueChanged.Invoke() in this example is akin to the following
//LogChange();
}
}
public MyStats(float value) //ALLOCATE MEMORY FOR A STAT
{
Value = value; //REPLACE VALUE WITH PARAMETER
OnValueChange += LogChange; //REGISTER (POINT TO) LOG CHANGE FUNCTION
}
private void LogChange()
{
//This will display when mystat value is changed - when OnValueChanged event is called
}
}
This class will register the private function LogChange() to the OnValueChange event. LogChange() will be called whenever the value is changed. However, if you notice I do not register the LogChange() until after the Value is set in the constructor, which means that nothing will be logged on instantiation. Although, any changed to the value after instantiation will be logged.
In the value setter, the OnValueChange?.Invoke(), in this example, is just like calling the LogChange() function directly. But, delegates are good at maintaining encapsulation. When the value is changed, some function, or functions, will be called via the OnValueChange call. However, MyStat does not need to know about the implementaiton of the method(s) called via OnValueChange. MyStat just needs to know that something gets called when the value is changed.
Delegates and Actions are part of event driven programming. Look at any UI api, such as unity. Provided link is for a unity button’s onclick event. All unity needs to know is that when the button is clicked, we need to do something else.