In this section, we are going to cover scriptable objects and their benefits. Similar to our interface, scriptable objects cover the same six classes. The reason for this is because our interface uses the SOActorModel and therefore creates an attachment with the other variables.
It is also good to remind ourselves of the Game Design Brief and how it is incorporated into the overview of the creation of our game.
Our game has three series of game objects that will hold similar properties: EnemyWave, EnemyFlee, and Player. These properties will include health, speed, score value, and more. The difference between each of these as described in the game design brief is the way they act and also how they are instantiated in our game.
Player will be instantiated at every level, EnemyWave will be spawned from EnemySpawner, and EnemyFlee will be placed in particular areas of the third level.
All of the mentioned game objects mentioned will relate to the SOActorModel object.
The following diagram is also a partial view of our game framework showing the scriptable object and the six classes that inherit it:
Similar to what was mentioned with the interface script is that the name of the scriptable object name starts withSO, which isn't a standard way of naming the script, but it's easier to identify as aScriptableObject.
The purpose of this scriptable object is to hold general values for each of the game objects it's being given to. For example, all game objects have a name, so within ourSOActorModelis a string namedactorName. ThisactorNamewill be used to name the type of enemy, spawner, or bullet it is.
Let's create a scriptable object:
- In the Project window in the Unity editor, create a script in the Assets/Resources/Scripts folder with the filename SOActorModel.
- Open the script and enter the following code:
[CreateAssetMenu(fileName = "Create Actor", menuName =
public class SOActorModel : ScriptableObject
public string actorName;
public AttackType attackType;
public enum AttackType
wave, player, flee, bullet
public string description;
public int health;
public int speed;
public int hitPower;
public GameObject actor;
public GameObject actorsBullets;
Save the script.
Inside the SOActorModel we will be naming most, if not, all of these variables in thePlayerscript. Similar to how an interface signs a contract with a class, theSOActorModel does the same because it's being inherited, but isn't as strict as an interface by throwing an error if the content from the scriptable object isn't applied.
The following is an overview of theSOActorModel code we just entered.
We named our scriptable object SOActorModelas a generic term to try and cover as many game objects as will likely use the scriptable object. This way of working also supports the SOLID principles we covered in the first chapter by encouraging us to try and keep our code concise and efficient.
The main categories we'll cover for this script are as follows:
- Importing libraries:As you can see, the only library we have imported in the SOActorModel script is theusing UnityEngine; no other libraries are required.
- Creating an asset:The CreateAssetMenu attribute creates an extra selection from the drop-down list in the Project window in the Unity editor when we right-click and select Create, as shown in the following screenshot:
- Inheritance: We aren't inheritingMonoBehaviour, but instead inheritingScriptableObject as it's a requirement when it comes to creating an asset.
- Variables: Finally, these are the variables that will be sent to our selected classes.
In the following sections, we are going to create assets from the scriptable object script to give our scripts different values.
Creating a PlayerSpawner ScriptableObject asset
With ourSOActorModelScriptableObjectmade, we can now create an asset that will act as a template that can be used not just byprogrammers, but also by designers who want to tweak game properties/settings without needing to know how to code.
To create an Actor Model asset, do the following:
- Back in the Unity editor, in the Project window, right-click and choose Create | Create Actor.
- Rename the newly created asset file in the Project window Player_Default and store the file in the Assets/Resources/Scripts/ScriptableObject folder.
- Click on the new asset and, in the Inspector window, you'll see the content of the asset.
The following screenshot shows the Actor Model asset's fields where I have entered in my own values:
Let's break down each of the values that have been added to our newly created asset:
- Actor Name: The name of the actor (in our case, this is Player).
- Attack Type: Choose to pick which category this game object belongs to.
- Description: Designer/internal notes that don't affect the game but can be helpful.
- Health: How many times can the player get hit before dying.
- Speed: Movement speed of the player.
- Hit Power: Determines how much damage the player will cause if it collides with the enemy.
- Actor: Place the player_ship prefab here (Assets/Resources/Prefab/Player/player_ship).
- Actors Bullets: Place the player_bullet prefab here (Assets/Resources/Prefab/Player/player_bullet).
We will add this asset to our PlayerSpawner script once it's built later on in the chapter. Let's move on to the next scriptable object asset.
Creating an EnemySpawner ScriptableObject asset
In this section, we are going to make our enemy asset to attach to EnemySpawner for later on in the chapter. For the sake of keeping our work fresh and together, let's continue with that before moving onto the EnemySpawner script.
To make an enemy asset, follow these instructions:
- Back in the editor, in the Project window, right-click and choose Create | Create Actor.
- Rename the new file to refer to what it's being attached to (BasicWave Enemy) and store the file in the Assets/Resources/Scripts/ScriptableObject location.
Click on the new script and our Inspector window will show the content of our script.
The following screenshot shows what the BasicWave Enemy asset is going to look like once we've finished:
Lets briefly go through each of the values for our enemy:
- Actor Name: enemy_wave
- Attack Type: Here, this is Wave. This explains what type of enemy it is and how it attacks the player.
- Description: Here, this reads Typically in groups. As mentioned before, it's more of a guideline than a rule to comment anything.
- Health: 1, which means it takes 1 hit to die.
- Speed: -30– because our enemy is moving from right to left, so we give it a minus figure.
- Hit Power: 1– which means that if this enemy collides with the player, it will cause 1 hit point of damage.
- Actor: Place the enemy_wave prefab here (Assets/Resources/Prefab/Enemies/enemy_wave).
- Actor Bullets: This enemy doesn't fire bullets.
Hopefully, you can see how useful scriptable objects are. Imagine continuing to develop this game with 50 enemies, where all we need to do is create an asset and customize it.
We are going to move on to the final scriptable object asset for this chapter in the next section.
Creating a PlayerBullet ScriptableObject Asset
In this section, we are going to create an asset for the player's bullet for when they fire. Like the last two sections, create an asset, name it PlayerBullet, and store it in the same folder as the other assets.
The following screenshot shows the final results for the PlayerBullet asset:
Let's briefly go through each variable's values:
- Actor Name: player_bullet.
- Attack Type: Bullet.
- Description: It is optional to enter any details about the asset here.
- Health: Our bullet has a health value of 1.
- Speed: 700.
- Hit Power: 1 sends a hit point of 1.
- Actor: Place the player_bullet prefab here (Assets/Resources/Prefab/Player/player_bullet).
- ActorBullets: None (Game Object).
In a later chapter, when we build a shop for our game, we will be able to buy power-ups for our player's ship. One of the power-ups will be similar to the one that we just made but the Actor Name will be different and the Hit Power will have a higher number.
Now we can move on to the next section and create the player's scripts and attach these assets to them.