Replace “switch” with Sctiptable Object in Unity

One of the design patterns in programming in Open-Closed Principle. It is part of the standard SOLID principles and takes it place at the ‘O’.

According to Wikipedia,

In object-oriented programming, the open/closed principle states “software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification“;[1] that is, such an entity can allow its behaviour to be extended without modifying its source code.

Okay! So we now understand by open we mean a class should be open for extension, and by closed we mean a class should be closed for modification. Let’s dive in, to make things clearer.

No alt text provided for this image

We have this rather beautiful scene where we have this NPC. We will have different kinds of NPCs with different behaviors.

To control NPCs we have a NpcControllerEnum script which will contain an enum of different NPC types and will react according to the type.

Let’s start with 2 NPC types

No alt text provided for this image

Now, here’s our controller script which switches to different behaviors based on the enum

No alt text provided for this image

So far, so good. We can tweak speeds from the inspector and change enemy type to get desired enemy behavior.

No alt text provided for this image

We needed 2 kinds of NPCs and we have them. If you are sure you won’t have any new types of enemy then we are good to go. But that’s rarely the case.

Let’s say we have a new requirements to add a new NPC which can wander around in a certain radius. What can we do? Obviously we can go to the enum and add another enemy type as RandomMover and add another case to our switch statement on NpcControllerEnum. If we do this we immediately break the Open-Closed Principle. Because to add new behaviors we are modifying the class, also modifying the enum. That class should be closed for modifications. What we can do is extend is. But from here extension is something that our switch statements with enums won’t allow us to do. So we have to think differently.

Let’s pause and think for a bit what we are doing here. We are checking the type of npc behavior in update and doing something that’s specific to that type. Essentially, we are “Behaving” according to the “Behavior Type”. Instead of being so specific, can we be more generic?

Let’s create a NpcBehavior abstract class and put an abstract method there named Behave(). By doing this, we are making a generic behavior. Now whenever we want a new behavior, we inherit this class and override the Behave function. Let’s make this inherit from Scriptable Object.

No alt text provided for this image

Now we have a generic behavior. From the Controller class, all we have to do now is create a field for NpcBehavior and from update just call npcBehavior.Behave()

No alt text provided for this image

Cool! All that switch, enum messy code is gone just like that. What the controller script is doing now is this

Controller: I don’t care what the behavior is! Just run the Behave function of that behavior

Very generic!

Let’s make our first behavior now

No alt text provided for this image

Simple and elegant. All we have to do is create a scriptable object instance of this and drag and drop that object in the controller. That’s it. Now we can add as many behaviors like this and just drag and drop its scriptable object instance to the npcBehavior field of the controller . It doesn’t matter how many behaviors we create we won’t have to modify the controller class for it, we just have to extend the NpcBehavior class.

Here is another behavior

No alt text provided for this image

I have added one more RandomMove Behavior and the final result looks like this

No alt text provided for this image

Here is the github link to the project files

Have fun!

Newsletter Updates

Enter your email address below and subscribe to our newsletter

Leave a Reply

Your email address will not be published. Required fields are marked *