Showing posts with label c_sharp. Show all posts
Showing posts with label c_sharp. Show all posts

Friday, July 31, 2026

ScriptableObjects In Unity And The Hidden Superpowers Most Overlook


When you first encounter ScriptableObjects, it's usually introduced as a way to store data outside of a scene. You create an asset, fill in some values in the Inspector, and suddenly you've got a cleaner alternative to hardcoded variables.

But that's only scratching the surface. It can do more than just hold data!

ScriptableObjects is one of Unity's most powerful and often misunderstood feature. If used correctly, it can simplify your architecture, reduce dependencies, improve reusability, and make your project significantly easier to maintain as it grows.

Unfortunately, it also has a reputation for being overengineered. Spend enough time on Unity forums, and you'll eventually find someone suggesting ScriptableObjects as the solution to virtually every problem. Need an inventory? ScriptableObjects. Dialogue? ScriptableObjects. AI? ScriptableObjects. Coffee machine broken? ...okay, perhaps not that one.

Like any tool, it's at its best when solving the right problem.

Let's deep-dive into what ScriptableObjects really are, when/how/why you should use them, and when it's definitely not the answer.

Thursday, July 30, 2026

Don't Ditch Coroutines for Async/Await in Unity Until You Read This

If you've only ever worked with coroutines, switching to async/await can feel almost magical. The code is cleaner, easier to read, and behaves much like synchronous code.

However, there's an important difference: Tasks are a .NET feature. Coroutines are a Unity feature.

That distinction affects how they interact with Unity's object lifecycle, scene management, and exception handling.

These differences are responsible for many of the mysterious NullReferenceExceptions and "WTF it worked yesterday!!" bugs that developers encounter when first adopting async.


Tasks don't adhere to Unity object lifetimes

This is arguably the biggest gotcha.

Imagine you write a simple async method to open a door:


public async Task OpenDoor()
{
    await Task.Delay(3000);

    animator.SetTrigger("Open");
}
  

Everything works perfectly until the player changes scenes, or destroys the object...or exits play mode. Three seconds later, the task resumes anyway. Now animator no longer exists.

NullReferenceException

You may wonder:

"The GameObject was destroyed. Why is this code still running?"

Because Tasks have no clue what a GameObject is. They're managed entirely by the .NET runtime.


Wednesday, July 29, 2026

Coroutines vs Async/Await vs Awaitable in Unity: Making Sense To Modern Asynchronous Programming

Coroutines have been pretty much the backbone of asynchronous programming in Unity for a long time. When you need to spawn enemies, fade a UI, load a level, or create cinematic sequences, chances are you wrote countless methods returning IEnumerator.

However, Unity has other options regarding this that may be better for your project.

Modern versions of Unity embrace C#'s async/await programming model and, more recently, introduced Awaitable, a Unity-specific asynchronous API that integrates directly with the engine. These additions don't replace coroutines outright but they complement them and, in many situations, offer cleaner, safer, and more powerful alternative.

Perhaps the challenge for many Unity game developers isn't learning the syntax, it's knowing which tool is better for the task at hand.

Let's take a deep-dive into Coroutines, async/await, and Awaitable, including threading, Task.Run(), CancellationToken, AwaitableCompletionSource, performance considerations, and strategies for migrating existing coroutine-based projects.

Tuesday, December 23, 2025

Singleton Game Design Patterns Done Right in Unity (With Code Examples)

Ahh, Singletons... probably one of the most debated game design patterns in Unity development. A quick Google search often reveals two camps. Those who swear by it, and those who avoid it like the plague. 

Not that long ago, I was in the latter camp. But ever since I ran into some issues, I'm switching back to the other side. Now, how do you use persistent and non-persistent Singletons effectively in Unity?

 

 

Let’s first briefly go over what a Singleton is for those unfamiliar with the concept.

 

Friday, December 19, 2025

Overengineering Code in Unity: When Good Game Architecture Can Become a Problem

Back in September of this year, I wrote an article about decoupling game systems in Unity with an EventBus. This is a crucial part of  game architectural design, and should be implemented in those areas of your project that make sense. Once you understand it, you're probably eager to implement it everywhere! But be aware that this can also lead to some unwanted results in your project.

Thursday, October 9, 2025

Greatly Increase Performance For Free With An Update Publisher In Unity!

Does your game or application in Unity use a lot of update loops that slow down performance? No need to install plug-ins or special packages, greatly increase performance for free with an update publisher in Unity. It makes you wonder why this isn’t a standard feature anyway (but that goes for a lot of things in Unity).

We’re basically going to make a SINGLE type of update loop for your entire project! As you can imagine, this will lead to a massive performance boost for your game, especially if you use a lot of scripts that implement any kind of update loop.

Understanding the issue: 

What's the problem? Let’s address the issue of update loops in the first place (like Update, FixedUpdate, or LateUpdate) in Unity, because it's more complex than you may think. 

When you put code in an update loop to move a game object, like transform.position += new Vector3(0, 0, 1) * Time.deltaTime;, under the hood a lot of different checks are being performed before the update loop is even validated and started. First, Unity checks if the object hasn’t been destroyed yet, then there's checks if the requirements have been met to be active at all. Even when it passes all these checks, Unity still needs to confirm that its own update method is functioning properly. 

So basically, even BEFORE Unity runs the actual update loop, it’s doing all these involved computations, behavior iterations, call validations, preparing to invoke the method, verifying all the arguments and then finally running the little piece of code you wrote (which hardly is a performance issue compared to the aforementioned. Yes, this even happens with empty update methods accidentally left behind in scripts!

This slows down your project tremendously, and gets worse the more update loops you have!  

When you have lots of objects that implement any update loop in Unity, you can see the problem if it needs to perform these under the hood checks constantly.

Come on!

But what can we do about it? This is yet another case where the Observer Design Pattern comes in!

 

The Solution: 

First, we’re going to make an UpdatePublisher that lives in the scene on its own GameObject. It holds the ONLY Update method in the game, and it’ll notify all the other listeners when it’s called.

The observer itself is an interface, we’ll call it IUpdateObserver:


public interface IUpdateObserver
{
    void ObservedUpdate();
}

Monday, September 29, 2025

6 Design Patterns Every Unity Developer Needs to Know

There are many reasons why there are design patterns every Unity developer needs to know. To know, and to fully understand that is. If you are a beginning game developer, you’ve undoubtedly already applied some of these patterns in your own game design project without even knowing it. Which pattern is the best depends on the nature and the game design structure. I use a combination of design patterns in my project; predominantly the observer and the singleton pattern. Below, we're going over all those design patterns, along with their pros and cons. Find out what the most common game design patterns are in Unity 6, with examples, so you can easily copy and paste them in your own project!



Tuesday, September 23, 2025

Top 10 Ways to Cache References in Unity 6 (and the Best Ones!), with Code Examples!

 

The beauty of the Unity Game Engine (and its downfall for some at the same time) is the amount of freedom it gives you when developing your game. There are multiple ways to structure something that result in the exact same outcome, but one approach is often better than another. Which one is best depends on your game design architecture, but overall it’s safe to say some methods are generally stronger regardless of your structure. Choosing the right way to cache references in Unity can greatly enhance the performance of your game.


Here are 10 ways you can cache references in Unity, along with their pros and cons, in no particular order:



Tuesday, September 16, 2025

Decoupling Game Systems in Unity with an EventBus

 

One of the biggest problems I used to run into while developing my game in Unity were referencing scripts and objects. Unless it's just a small project that can be handled by a handful of scripts, if your game gets any larger you quickly realize this can become a big issue. Before you know it, you're dealing with a ton of spaghetti code referencing scripts all over the place. That's where game architecture comes into play.

As you continue your game development career, you'll notice that game architecture becomes more and more important. It's something you probably didn't give much thought to when you started out, but now it's super important to understand which game architecture path you want to implement in your game.

Does the UI panel need to know if your player takes damage? Or does your Audio Manager need to know if the state of your game changes? Already you can see there is some referencing involved.

Let me show you the "old way" I used to decouple scripts from one another, and the new way — a technique I'm using now to make it even more expandable.

The old way featured a static class that acted like a middleman between scripts that needed information from each other.

The script was simply called GameEvents.cs. and looked like this with an Audio event as an example:


using System;
using UnityEngine;
  
namespace Munnica.Events
{
    public static class GameEvents
    {
        /// 
        /// If audio needs to be played
        /// 
        public static Action<AudioClip> OnAudioPlay = delegate { };               
    }
}
  

Then in another script, let's say AudioManager.cs, you would then subscribe to, and unsubscribe from, this GameEvent:


namespace Munnica.Managers
{
    public class AudioManager : MonoBehaviour
    {
        private void OnEnable()
        {
            GameEvents.OnAudioPlay += PlayAudio;            
        }

        private void OnDisable()
        {
            GameEvents.OnAudioPlay -= PlayAudio;            
        }

        private void PlayAudio(AudioClip clip)
        {
            // Cached references from AudioManager would then be called
            // e.g. _audioSource.clip = clip; _audioSource.Play();
        }
    }
}
  

Audio, for example, would then be triggered from another script by means of GameEvents.OnAudioPlay, which in turn would play the passed through audioclip

The problem that I realized (after having about 20 GameEvents in the script), was that this technique wasn't very scalable. What if I also wanted to control the volume of the audio, or the pitch? GameEvents that took care of th UI were even worse! Images, text components etc, have a lot more possibilities. This would all have to be restructured and refactored if I wanted to add extra things.

The solution? An EventBus!!

A bus, not to be confused with the vehicle :P, in computing terms is a communication system that transfers data between components. Exactly what we need for our game development project that's in dire need of decoupling!

Understanding how the 'old-event' system works (as described above), is a huge plus since it behaves similarly - but not necessary to implement this new system in your own project.

Let’s walk through how you can set up your own EventBus system step by step.

The EventBus system looks like this:

Step 1: Create a static class EventBus


using System;
using System.Collections.Generic;

namespace Munnica.Events
{
    public static class EventBus
    {
        private static readonly Dictionary _eventTable = new();

        public static void Subscribe(Action callback)
        {
            if (_eventTable.TryGetValue(typeof(T), out var existingDelegate))
            {
                _eventTable[typeof(T)] = (Action)existingDelegate + callback;
            }
            else
            {
                _eventTable[typeof(T)] = callback;
            }
        }

        public static void Unsubscribe(Action callback)
        {
            if (_eventTable.TryGetValue(typeof(T), out var existingDelegate))
            {
                _eventTable[typeof(T)] = (Action)existingDelegate - callback;
            }
        }

        public static void Publish(T eventData)
        {
            if (_eventTable.TryGetValue(typeof(T), out var del))
            {
                ((Action)del)?.Invoke(eventData);
            }
        }

        public static void DebugSubscribers()
        {
            foreach (var kvp in _eventTable)
            {
                var type = kvp.Key;
                var del = kvp.Value;

                UnityEngine.Debug.Log($"Event Type: {type.Name}");

                if (del != null)
                {
                    foreach (var d in del.GetInvocationList())
                    {
                        UnityEngine.Debug.Log($"  -> {d.Method.Name} from {d.Target}");
                    }
                }
            }
        }


    }


}

  

As you can see, there are a few additions compared to the previous GameEvent system.

The static 'Subscribe' method is similar to the += subscribe in GameEvents. This time with the addition that we're now using Generics to implement the TYPE we're going to communicate with. The subscription is then stored in an event table (dictionary). In the same class, we're also implementing 'Unsubscribe', this ensures that we can easily unsubscribe from the EventBus in the method OnDisable in any script!

Step 2: (this is where the magic is going to happen!) Create structs: special data containers tailored to your project.

In my game development project, I use all kinds of structs for EventBus, the following example is how I play audio by means of a struct:


using UnityEngine;


namespace Munnica.Events
{
    public struct PlaySoundEvent
    {
        public AudioClip Clip;
        public Vector3 Position;
        public float Volume;
        public int Channel;
        public bool Stop;


        public PlaySoundEvent(AudioClip clip, Vector3 position, int channel = 1, float volume = 1f, bool stop = false)
        {
            Clip = clip;
            Position = position;
            Channel = channel;
            Volume = volume;
            Stop = stop;

        }
    }
}


  

As you can see, it's totally customizable and expandable now! This struct 'PlaySoundEvent' has a constructor that assigns the parameters that need to be implemented! I can now not only decide which Audioclip to play, also I can assign the position, the channel it needs to play through (I have 3 different AudioSources), the volume level and if the audio needs to stop at any given moment. Let's say later on I want to also include the pitch level, or something else, it can be easily added on without breaking any code!

Now, how do we call this Event? Remember in our static class EventBus we wrote the Publish method? Exactly, that's what we're going to use to 'invoke' this event!

Step 3: Publish the event!

From any script, we can invoke this event by:


EventBus.Publish(new PlaySoundEvent(_scannerLoadingSFX, Vector3.zero, 2, 1f));
  

By means of customized structs, perfectly tailored to any small- midsized project, we've now completely decoupled our game system! AudioManager, for example, doesn't need to know which script is playing an audioclip, it just knows it needs to play the clip that's coming in. The same goes for the script pushing the audioclip, it doesn't need to know which script is responsible for playing the clip. It just needs to 'submit' the clip to a subscriber. I recently completely overhauled my project to implement the EventBus system. I've been working with this new system for quite some time now, and I can't go back anymore!

Final note about subscribers:

One last note, and that's about the EventBus subscribers. At some point, your going to have more than one event. In fact, it's likely you'll be ending up with lots of custom structs that all do something in your project. With the 'old-game event system', you could just look at the list GameEvents and see how many events there were in your game (although you still weren't able to see which scripts were assigned to that event unless you did a work around). Now, with EventBus, there is a special included method 'DebugSubscribers' that will allow you to see which game objects (scripts) are subscribed to which event!

In my GameManager class (which is a persistent singleton), I just have a simple boolean _showEventSubscribers, that (when ticked) prints out all the actives subscribers to the console in Unity by means of this code:


	if (_showEventBusSubscribers) { EventBus.DebugSubscribers(); }
  

I hope that you can apply this technique in your own project. I found it the best way to decouple scripts in Unity game development! If you have any questions, (or perhaps know even a better way!) do not hesitate to reach out.

This article may contain typos or grammarly incorrect sentence structures, I'm a gamedeveloper, not an editor or proofreader :P

Happy coding!

Wednesday, March 5, 2025

The Best Way To Handle Raycast in Unity C#

 

Raycasts in Unity3D are extremely powerful if implemented correctly. They can handle anything from checking ground to detecting objects in your game. I’ve come across many tutorials that implement this raycast feature, however most of them are unintuitive and not very expandable. Unity allows you to build pretty much anything. However, this creative freedom can also be a downside if you’re not careful. A feature that works is not necessarily the best way of doing something.


Friday, September 16, 2022

The Hidden Labyrinth indie game devlog update

A quick update regarding the ongoing Unity project "The Hidden Labyrinth", an upcoming first person survival horror game.

Temporary title screen of "The Hidden Labyrinth"

The player has to navigate a mysterious forest where the entrance to the hidden labyrinth can be found. Before that, there's an opening scene telling a bit about the background story. Once the player is in the forest, it's time to explore all its mysteries and find a way to get into the labyrinth.

Some secrets can only be revealed by your special ability...

Eventually the player will obtain an ability to see 'the forbidden', hidden objects in the game that add to the horror and puzzle element. I've always been a big fan of that concept :)


A distorted effect will let the player know what can be seen and what can't.

It's safe to say the outline of the forest environment is pretty much done. This was an enormous task, things will (hopefully) develop a bit faster from here on out.


Crows play an important role in the game.

Although a lot of progress has been made, there's still a lot left to do in the first scene alone. Most of the time goes to proper level design and puzzle mechanics. 

I'm aiming on Halloween '22 to release a demo of the game (first scene).


Follow me on twitter for the latest info about The Hidden Labyrinth.

Thursday, January 13, 2022

The Hidden Labyrinth devlog update!

It's been awhile since the announcement of "The Hidden Labyrinth" back in October! A lot has happened and changed since then. One of the major changes was that I had to rework the entire forest map (terrain) in the scene. I was simply not happy with the initial layout of the forest, so I had to start over - this time making the height and size as I had intended. With that change also came the switch to URP instead of the Legacy (built-in) rendering pipeline. This decision has some drawbacks - such as not being able to implement a flash light effect I really had my eye on (light cookies aren't supported in URP), but there are work-arounds to 'fix' this. Overall the game looks and plays much better with the new Universal Rendering Pipeline implementation. In the same scene, there is a part of the labyrinth the player can explore. This is where you can obtain your first special ability in the game; being able to see 'the forbidden'. This ability enables you to see things that are not visible normally - opening the pathway to create puzzles in the game that make use of this feature.


The front gate of "The Hidden Labyrinth" - the lion heads on either side are 'placeholders' and are going to be replaced eventually with a different model, probably one I'm going to create myself in Blender.

Furthermore, I created some of my own shaders which are used to highlight some objects in the game that are normally hidden. 

The forest scene itself is from an asset pack by NatureManufacture. They use extremely detailed models and textures for trees, rocks, grass, leaves - pretty much anything you can think of in a real forest.

The area where the player is going to be able to pickup their special ability that enables them to see 'the forbidden'.

The forest also has many particle effects - one that I made myself (and particularly proud of!) creates the illusion of fog (animated), that slowly moves through the forest - spooky!

The scene view with all particle and post-processing effects turned-off!

The biggest challenge for me was to implement the 'lookatobjects' system. This basically takes care of detecting what and where the player is looking at. If there's an interactable object, the crosshair in the center will change to an 'E' (depending on which platform the game is played) to let the player know they can interact with the object. I built this system myself from ground-up because I wanted to know exactly how to code works. It's likely the foundation of not only this game but also future games.

The project is doing extremely well and I'm making some great progress. Now that I have the basics set up, expect more frequent updates in the future!

One more screenshot of the forest where the player initially has to find the labyrinth...

Follow on twitter if you want to stay up to date - I know I don't update this site very often.



Tuesday, August 24, 2021

Introducing Hangman X

This game is actually a Unity course gotten out of hand! The game itself is just Hangman, a simple concept of guessing letters to figure out what the secret word is. Guess it right and you'll be able to go to the next round with the points earned from the previous round. The faster you guess the word, the more points can be obtained. The aim of the game is to score as high as possible. This game features five categories: Celebrities, Cities, Food & Drink, Animals and Movies & TV! There are tons of words to unravel, all handpicked by myself :)

Below is a gameplay video (demo showcase) on YT.



Game will be released this week on https://munnica.itch.io/ and can be played for absolutely free! Follow me @ https://twitter.com/munnica1 to stay tuned regarding the latest updates and releases!

Thursday, May 13, 2021

How to use delegates and events in Unity C#

One of the most powerful tools in Unity3D C# coding I've come across so far is the implementation of delegates and events. It may be hard to learn at first, and that's because in order to understand the purpose of delegates, you need to understand how events are handled. And in order to understand how events are handled, you need to understand delegates. 

Sounds confusing so far? Bear with me. It's actually pretty simple, the important thing here is to learn delegates first! Even if its implementation doesn't make any sense to you, if you understand how it works you have a solid foundation to understand events (where the real power lies!). I've seen countless tutorials on delegates and events, but in my opinion they were very hard to understand. Hopefully my explanation will make it a bit easier to understand delegates and events.

This tutorial is for those who already have a basic/intermediate understanding of C# in Unity3D.


Why you should learn it.

Once you understand it, it's an extremely powerful asset in your coding toolbox, which you can pretty much implement in any Unity C# project you're working on. It also makes your code a lot more cleaner and efficient.


What does it do?

Within one click of a mouse button or any assigned key or trigger, you can make multiple things happen at once without having to repeat code.


What are delegates?

When you declare a delegate you can store methods in a variable. 

The way I understood it best is comparing it to a .zip file. One file (method) that hold multiple files (methods) inside, you can add or remove files (methods) as you go along. In the end you can call that zip file (method) and all the files inside will be executed at once.

That's the basic explanation, there's more to it of course but at this point this is all you need to know. Declaring a delegate is easy, for this example I'm going to make a button in the scene.


  1. Add the button in the hierarchy (right-click UI > button). 
  2. Add component and call it "OnButtonClick", or whatever you want.
  3. Assign "OnButtonClick" script to button. (Add component).
Open up your new C# script, in my case OnButtonClick, and declare a delegate named 'Action Click'. (on line 7, you can also name this whatever you want). Then you give the delegate a name (on line 8) and make it a public static event. Make sure you create a public method for your button that also checks to see of the delegate is not equal to null to prevent errors in the future, and assign onClick();

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnButtonClick : MonoBehaviour
{
    public delegate void ActionClick();
    public static event ActionClick onClick;
    

    public void OnClick()
    {
        
        if (onClick != null)
        {
            onClick();
        }
        
    }

}

Hook it up to your button:



That's it! You created your first delegate that gets activated when you click the button! But what can you do with it? As of right now, it doesn't do much of course. Nothing is being triggered yet. 

In order to see what it can do you need to create a simple cube in your scene for instance. Create a cube and attach a script called CubeController to it (or whatever you want to name it). Open up CubeController script and add:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CubeController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        OnButtonClick.onClick += ChangeColor;
        OnButtonClick.onClick += DoSomethingElse;
        OnButtonClick.onClick += DoSomethingElse2;
        OnButtonClick.onClick += DoSomethingElse3;
    }

    private void ChangeColor()
    {
        GetComponent<MeshRenderer>().material.color = Color.red;
    }

    private void DoSomethingElse()
    {
        print("Do something else");
    }

    private void DoSomethingElse2()
    {
        print("Do something else 2");
    }

    private void DoSomethingElse3()
    {
        print("Do something else 3");
    }

}

For this example I'm changing the color of the cube to red, as well as three other methods you can check in the console window in Unity.