{"id":31245,"date":"2018-07-06T15:14:00","date_gmt":"2018-07-06T15:14:00","guid":{"rendered":"http:\/\/www.gamasutra.com\/view\/news\/321434"},"modified":"2018-07-06T15:14:00","modified_gmt":"2018-07-06T15:14:00","slug":"blog-how-to-use-c-events-in-unity","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2018\/07\/06\/blog-how-to-use-c-events-in-unity\/","title":{"rendered":"Blog: How to use C# Events in Unity"},"content":{"rendered":"<p><strong><i><small> The following blog post, unless otherwise noted, was written by a member of Gamasutra\u2019s community.<br \/>The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company. <\/small><\/i><\/strong> <\/p>\n<hr \/>\n<h2>Objective<\/h2>\n<p>The main objective of this blog post is to give you an idea about how to use C# Events in Unity.<\/p>\n<p><strong>What is problem with Delegates?<\/strong><\/p>\n<p><strong>What is an Event?<\/strong><\/p>\n<p><strong>Why Events are used?<\/strong><\/p>\n<p><strong>How to declare an Event?<\/strong><\/p>\n<p><em>You may have all these questions in your mind.<\/em><\/p>\n<p><em>Don\u2019t worry, you are at the right place.<\/em><\/p>\n<p><strong>Let\u2019s start, Do you remember the problem of Delegates?<\/strong><\/p>\n<p><em>If we use a single delegate after the use of multicast delegates then it will reset the existing invocation list. <\/em><\/p>\n<p><em>This situation is very difficult to track if multiple classes subscribe to the same delegate.<\/em><\/p>\n<p><em>This is the reason why we have Events.<\/em><\/p>\n<p><em>Let\u2019s see how they work.<\/em><\/p>\n<p>Events are a type of special delegates which are used when you want to notify other classes when something happens. Like, on <strong>GameStart<\/strong>, on <strong>Gameover<\/strong>.<\/p>\n<p><strong>Let\u2019s take a look on declaration and use of an Events.<\/strong><\/p>\n<p><strong>1. Declare a Delegate<\/strong><\/p>\n<pre><code>public delegate void OnGameStart();<\/code><\/pre>\n<p><strong>2.Create an Event<\/strong><\/p>\n<pre><code>public static event OnGameStart onGameStart;<\/code><\/pre>\n<p><strong>3. Point to method<\/strong><\/p>\n<pre><code>onGameStart += Move;<\/code><\/pre>\n<p><strong>4. Invoke an Event<\/strong><\/p>\n<pre><code>onGameStart ();<\/code><\/pre>\n<p><strong>Let&#8217;s, create a simple game using Event Delegate.<\/strong><\/p>\n<p><strong>Step 1<\/strong><\/p>\n<ul>\n<li>Create an empty <strong>GameObject <\/strong>name it as you like.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 2<\/strong><\/p>\n<ul>\n<li>Create C# script name it <strong>EventManager<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p>Write following code in <strong>EventManager.cs<\/strong><\/p>\n<pre><code>public class EventManager : MonoBehaviour {&#013; public delegate void OnButtonClick();&#013; public static event OnButtonClick onButtonClick;&#013; public void RaiseOnButtonClick() {&#013; if (onButtonClick != null) {&#013; onButtonClick();&#013; }&#013; }&#013; }<\/code><\/pre>\n<p><strong>Step 3<\/strong><\/p>\n<ul>\n<li>Assign it to an empty <strong>GameObject<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 4<\/strong><\/p>\n<ul>\n<li>Create a 2d object and assign knob as sprite in <strong>SpriteRenderer<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 5<\/strong><\/p>\n<ul>\n<li>Create\u00a0 C# script name <strong>PlayerTransformAndColor.<\/strong><\/li>\n<p>&#013;\n<\/ul>\n<p>Write following code in <strong>PlayerTransformAndColor.cs<\/strong><\/p>\n<pre><code>public class PlayerTransformAndColor : MonoBehaviour {&#013; &#013; public SpriteRenderer spriteRenderer;&#013; public Color color1, color2;&#013; private void OnEnable()&#013; {&#013; EventManager.onButtonClick += ChangePosition;&#013; EventManager.onButtonClick += ChangeColor;&#013; }&#013; public void ChangePosition() {&#013; transform.position += Vector3.one * 2;&#013; }&#013; public void ChangeColor() {&#013; spriteRenderer.color = color2;&#013; }&#013; }<\/code><\/pre>\n<p><strong>Step 6<\/strong><\/p>\n<ul>\n<li>Assign it to empty <strong>GameObject<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p>Now let\u2019s do some changes in <strong>PlayerTransformAndColor.cs<\/strong><\/p>\n<pre><code>public class PlayerTransformAndColor : MonoBehaviour {&#013; public SpriteRenderer spriteRenderer;&#013; public Color color1, color2;&#013; private void OnEnable()&#013; {&#013; EventManager.onButtonClick += ChangePosition;&#013; EventManager.onButtonClick += ChangeColor;&#013; EventManager.onButtonClick = ChangeRotation;&#013; }&#013; public void ChangePosition() {&#013; transform.position += Vector3.one * 2;&#013; }&#013; public void ChangeColor() {&#013; spriteRenderer.color = color2;&#013; }&#013; public void ChangeRotation() {&#013; transform.Rotate(0, 90, 0);&#013; }&#013; &#013; }<\/code><\/pre>\n<p>You may find the error. Like shown in below,<\/p>\n<p><img decoding=\"async\" alt=\"error\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2018\/07\/blog-how-to-use-c-events-in-unity.jpg\" \/><\/p>\n<p><strong>Got the\u00a0 idea, How Events overcome the problem of Delegates.??<\/strong><\/p>\n<p>Events adds a layer of abstraction and protection on delegate, this protection prevents client of the delegate from resetting the delegate and invocation list. \u00a0<\/p>\n<p>Now let\u2019s take one more practical example. That gives you more clear idea about how event handle multiple event listeners by only one event Invocation.<\/p>\n<p><strong>For this, we\u2019ll follow these steps.<\/strong><\/p>\n<p><strong>Step 1<\/strong><\/p>\n<ul>\n<li>Create an empty GameObject name it <strong>EventManager<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 2<\/strong><\/p>\n<ul>\n<li>Create C# scrip and name it <strong>Eventmanager<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p>Write following code in <strong>EventManager.cs<\/strong><\/p>\n<pre><code>public class EventManager : MonoBehaviour {&#013; public delegate void OnRest(); \/\/Declare a Delegate&#013; public static event OnRest onReset; \/\/Create an Event&#013; public delegate void OnReStart(); \/\/Declare a Delegate&#013; public static event OnReStart onReStart; \/\/Create an Event&#013; public static void RaiseOnReset()&#013; {&#013; if (onReset != null)&#013; {&#013; onReset(); \/\/Invoke an Event&#013; }&#013; }&#013; public static void RaiseOnReStart()&#013; {&#013; if (onReStart != null)&#013; {&#013; onReStart(); \/\/Invoke an Event&#013; }&#013; }&#013;\n}<\/code><\/pre>\n<p><strong>Step 3<\/strong><\/p>\n<ul>\n<li>Assign it to an empty <strong>GameObject(EventManager)<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 4<\/strong><\/p>\n<ul>\n<li>Create an empty <strong>GameObject<\/strong> name it <strong>EventHandler<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 5<\/strong><\/p>\n<ul>\n<li>Create C# script name it <strong>EventHandler<\/strong><\/li>\n<p>&#013;\n<\/ul>\n<p>Write following code in <strong>EventHandler.cs<\/strong><\/p>\n<pre><code>public class EventHandler : MonoBehaviour&#013;\n{&#013; void Update()&#013; {&#013; if (Input.GetKeyDown(KeyCode.P))&#013; {&#013; EventManager.RaiseOnReset(); \/\/ Function call to invoke an Event&#013; }&#013; else if (Input.GetKeyDown(KeyCode.S))&#013; {&#013; EventManager.RaiseOnReStart(); \/\/ Function call to invoke an Event&#013; }&#013; }&#013;\n}<\/code><\/pre>\n<p><strong>Step 6<\/strong><\/p>\n<ul>\n<li>Assign it to an empty <strong>Gameobject(EventHandler)<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><strong>Step 7<\/strong><\/p>\n<p>Create a 3D game <strong>object(Cube)<\/strong>.<\/p>\n<p><strong>Step 8<\/strong><\/p>\n<ul>\n<li>Create C# script name it <strong>ObjectMotion<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p>Write following code in <strong>ObjectMotion.cs<\/strong><\/p>\n<pre><code> public class ObjectMotion : MonoBehaviour&#013; {&#013; private float minRange, maxRange;&#013; private float speed, restartSpeed;&#013; private Vector3 newPosition;&#013; private void OnEnable()&#013; {&#013; EventManager.onReset += Reset;&#013; EventManager.onReStart += Restart;&#013; }&#013; void Start()&#013; {&#013; minRange = 1;&#013; maxRange = 3;&#013; speed = Random.Range(minRange, maxRange);&#013; restartSpeed = speed;&#013; }&#013; void Update()&#013; {&#013; newPosition = transform.position;&#013; newPosition.x = Mathf.Sin(Time.time) * speed;&#013; transform.position = newPosition;&#013; }&#013; private void OnDisable()&#013; {&#013; EventManager.onReset -= Reset;&#013; EventManager.onReStart -= Restart;&#013; }&#013; public void Reset()&#013; {&#013; speed = 0;&#013; }&#013; public void Restart()&#013; {&#013; speed = restartSpeed;&#013; }&#013; }<\/code><\/pre>\n<p><strong>Step 9<\/strong><\/p>\n<ul>\n<li>Assign it to 3D <strong>GameObject(Cube)<\/strong>.<\/li>\n<p>&#013;\n<\/ul>\n<p><em>Now create multiple copies of 3D GameObject.<\/em><\/p>\n<p><em>Run Unity, and press &#8220;P&#8221; to reset the position and &#8220;S&#8221; to restart the motion.<\/em><\/p>\n<p>From the above examples we may come to the\u00a0 following conclusion,<\/p>\n<div class=\"border-box\">\n<h3 class=\"heading-medium\"><span class=\"box\">Conclusion<\/span><\/h3>\n<ul>\n<li>Delegates and Events help us to write modular and reusable code.<\/li>\n<p>&#013; <\/p>\n<li>Always use Events together with Delegates for safety.<\/li>\n<p>&#013; <\/p>\n<li>Do not forget to unsubscribe otherwise, it will lead to memory leak.<\/li>\n<p>&#013;\n<\/ul>\n<\/div>\n<p><em>Feel free to contact us if you really liked this blog. And don\u2019t forget to share your comments below!<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The following blog post, unless otherwise noted, was written by a member of Gamasutra\u2019s community.The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company. Objective The main objective of this blog post is to give you an idea about how to use C# Events in Unity. What is [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":31246,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"class_list":["post-31245","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/31245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=31245"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/31245\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/31246"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=31245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=31245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=31245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}