LAB MANUAL
Unity Game Development
Scriptable Objects in Unity
Creating Data Containers for Game Development
Table of Contents
TOC \h \o "1-3"
Lab Overview
This lab manual provides a comprehensive guide to understanding and
implementing Scriptable Objects in Unity. You will learn how to create data
containers that can efficiently store game information such as character stats, item
properties, and card data. Through a hands-on example of creating a card system
similar to Hearthstone, you will master the fundamentals of Scriptable Objects and
their practical applications in game development.
Lab Objectives
By the end of this lab, students will be able to:
1. Understand the purpose and benefits of Scriptable Objects in Unity
2. Create custom Scriptable Object templates for storing game data
3. Generate Scriptable Object instances from templates
4. Reference and access Scriptable Object data in scripts
5. Display Scriptable Object data on UI elements
6. Implement methods within Scriptable Objects
7. Apply Scriptable Objects to real-world game development scenarios
Duration
Estimated Time: 2-3 hours
Prerequisites
Before starting this lab, students should have:
• Basic understanding of C# programming
• Familiarity with Unity Editor interface
• Knowledge of Unity UI system (Canvas, Text, Image components)
• Understanding of MonoBehaviour and basic Unity scripting
• Experience with prefabs and Unity's project hierarchy
Required Materials
• Unity Editor (version 2019.4 LTS or later recommended)
• Visual Studio or any C# IDE
• Sprite images for card artwork (any game character images)
• Card UI template (provided in project setup)
Theoretical Background
What are Scriptable Objects?
Scriptable Objects are a powerful Unity feature that provides an efficient way to store
and manage data independently from game objects. Unlike MonoBehaviour scripts
that must be attached to GameObjects in a scene, Scriptable Objects exist as
standalone assets in your project.
In simple terms, Scriptable Objects are data containers that allow you to create
reusable, modular data structures. They are particularly useful when you need to
store large amounts of data that can be shared across multiple objects or scenes.
Why Use Scriptable Objects?
Problem with Traditional Approaches:
When creating games, especially RPGs or card games, you often need to create
many similar items with different properties. For example, hundreds of items,
weapons, or cards each with their own stats. Using prefabs for this purpose has
several drawbacks:
• Prone to errors when manually copying and modifying values
• Inconvenient to manage large numbers of prefab variants
• Memory inefficient as each prefab instance stores duplicate component data
• Difficult to maintain consistency across similar items
Benefits of Scriptable Objects:
• Extremely lightweight (typically only 1 KB per object)
• Easy to create and modify through Unity's Inspector
• Can be created and edited at runtime or in the editor
• Promote clean, modular code architecture
• Shareable across multiple scenes and GameObjects
• Support inheritance for creating specialized data types
Common Use Cases
Scriptable Objects are ideal for:
• RPG item databases (weapons, armor, consumables)
• Character stats and attributes
• Card game data (as demonstrated in this lab)
• Enemy configurations and AI parameters
• Audio clip collections
• Game configuration settings
• Dialogue systems and quest data
• Level design templates
How Scriptable Objects Work
The workflow for Scriptable Objects follows a two-step process:
Step 1: Create a Template
First, you define a C# class that inherits from ScriptableObject. This class acts as a
template that specifies what information each object should hold. Think of it as
creating a blueprint for your data structure.
Step 2: Create Instances
Once you have your template, you can create as many instances (objects) as
needed from that template through Unity's Create Asset Menu. Each instance stores
its own unique data while following the structure defined in the template.
Lab Procedure
In this lab, we will create a card system for a Hearthstone-style card game. Each
card will have properties like name, description, artwork, mana cost, attack value,
and health. We will use Scriptable Objects to efficiently store and manage this card
data.
Part 1: Project Setup
1.1 Scene Preparation
8. Create a new Unity scene or open an existing one
9. Create a Canvas for UI elements (GameObject > UI > Canvas)
10. Add an Image component to represent the card background
11. Create the following UI Text elements as children of the card:
a) Name Text
b) Description Text
c) Mana Cost Text
d) Attack Value Text
e) Health Value Text
12. Add an Image component for the card artwork
13. Apply a mask to the artwork image to fit the card design
Note: Position and style these UI elements according to your card design
preferences.
Part 2: Creating the Scriptable Object Template
2.1 Create the Card Script
14. In the Project window, right-click and select Create > C# Script
15. Name the script 'Card'
16. Double-click to open the script in your IDE
2.2 Modify the Script Structure
Replace the default code with the following:
using UnityEngine;
[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
public class Card : ScriptableObject
{
public new string name;
public string description;
public Sprite artwork;
public int manaCost;
public int attack;
public int health;
}
2.3 Code Explanation
Let's break down the important parts of this code:
Inheritance from ScriptableObject:
public class Card : ScriptableObject
Instead of inheriting from MonoBehaviour, we inherit from ScriptableObject. This tells
Unity that this script will act as a data container rather than a component attached to
a GameObject.
CreateAssetMenu Attribute:
[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
This attribute adds an entry to Unity's Create menu, allowing you to easily create
new card instances. The fileName parameter sets the default name for new cards,
and menuName determines where in the Create menu the option appears. You can
create submenus using forward slashes, for example: menuName =
"Cards/Character Card".
The 'new' Keyword for Name:
public new string name;
Every Unity object has a built-in 'name' variable. Using the 'new' keyword tells the
compiler to use this definition instead of the inherited one. Alternatively, you could
rename this to 'cardName' to avoid the conflict.
Data Fields:
Each public field defines a property that our cards will have:
• name (string): The card's name
• description (string): Descriptive text about the card
• artwork (Sprite): The visual image for the card
• manaCost (int): Resource cost to play the card
• attack (int): Attack power value
• health (int): Health/durability value
17. Save the script and return to Unity
18. Wait for Unity to compile the script (this may take a few seconds)
Part 3: Creating Card Instances
3.1 Create Your First Card
19. In the Project window, right-click in your desired folder
20. Navigate to Create > Card
21. A new card asset will be created with the default name 'New Card'
22. Rename it to 'Edwin' (or any character name you prefer)
3.2 Configure the Edwin Card
23. Select the Edwin card asset
24. In the Inspector window, fill in the following fields:
f) Name: Edwin
g) Description: the baddest guy in town
h) Artwork: Select a sprite image from your project
i) Mana Cost: 3
j) Attack: 2
k) Health: 2
3.3 Create a Second Card
25. Right-click in the Project window again
26. Select Create > Card
27. Name this card 'Tirion'
28. Configure Tirion with the following properties:
l) Name: Tirion
m) Description: His light shall burn you!
n) Artwork: Select a different sprite image
o) Mana Cost: 6
p) Attack: 6
q) Health: 6
Checkpoint: At this point, you should have two Scriptable Object assets in
your project, each containing unique card data. Notice how small these files
are - typically only 1 KB each!
Part 4: Displaying Card Data in the Game
4.1 Create the CardDisplay Script
Now that we have our card data stored, we need a script to read and display this
data on our UI card.
29. Select your card GameObject in the Hierarchy
30. In the Inspector, click 'Add Component'
31. Search for 'New Script' and select it
32. Name the script 'CardDisplay'
33. Click 'Create and Add'
34. Double-click the script to open it in your IDE
4.2 Initial CardDisplay Code
First, let's create a simple version that just prints the card name:
using UnityEngine;
public class CardDisplay : MonoBehaviour
{
public Card card;
void Start()
{
[Link]([Link]);
}
}
Code Explanation:
• We create a public Card variable named 'card' - this will hold a reference to
our Scriptable Object
• In the Start method, we access the card's name property and print it to the
console
• The 'card' variable with lowercase 'c' references our Card class (capital 'C')
4.3 Test the Basic Display
35. Save the script and return to Unity
36. Select your card GameObject
37. In the Inspector, you'll see a 'Card' field in the CardDisplay component
38. Drag the Edwin card asset from your Project window into this field
39. Press Play
40. Check the Console window - you should see 'Edwin' printed
Part 5: Adding Methods to Scriptable Objects
Scriptable Objects can contain methods, not just data. Let's add a Print method to
our Card class.
5.1 Update the Card Script
41. Open the [Link] script
42. Add the following method inside the Card class:
public void Print()
{
[Link](name + ": " + description + ". The card costs " +
manaCost);
}
The complete [Link] script should now look like this:
using UnityEngine;
[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
public class Card : ScriptableObject
{
public new string name;
public string description;
public Sprite artwork;
public int manaCost;
public int attack;
public int health;
public void Print()
{
[Link](name + ": " + description + ". The card costs " +
manaCost);
}
}
5.2 Update CardDisplay to Use the Print Method
43. Open the [Link] script
44. Replace the [Link] line in Start with:
[Link]();
45. Save and return to Unity
46. Press Play
47. The Console should now display: 'Edwin: the baddest guy in town. The card
costs 3'
Part 6: Complete UI Integration
Now let's display all the card information on our UI elements instead of just in the
console.
6.1 Update CardDisplay Script
Replace the entire [Link] script with the following:
using UnityEngine;
using [Link];
public class CardDisplay : MonoBehaviour
{
public Card card;
public Text nameText;
public Text descriptionText;
public Image artworkImage;
public Text manaText;
public Text attackText;
public Text healthText;
void Start()
{
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link]();
[Link] = [Link]();
[Link] = [Link]();
}
}
Code Explanation:
• We add 'using [Link];' at the top to access UI components
• We declare public variables for each UI element (Text and Image
components)
• In Start, we assign values from the card to each UI element
• For Text components, we set the .text property
• For the Image component, we set the .sprite property
• We use .ToString() to convert integer values to strings for display
6.2 Connect UI Elements
48. Save the script and return to Unity
49. Select your card GameObject
50. In the Inspector, you'll now see slots for all the UI references
51. Drag and drop each UI element from the Hierarchy into its corresponding slot:
r) Drag the Name Text object to the Name Text slot
s) Drag the Description Text object to the Description Text slot
t) Drag the Artwork Image object to the Artwork Image slot
u) Drag the Mana Text object to the Mana Text slot
v) Drag the Attack Text object to the Attack Text slot
w) Drag the Health Text object to the Health Text slot
6.3 Test the Complete Display
52. Make sure the Edwin card is assigned to the Card slot
53. Press Play
54. You should see all of Edwin's information displayed on the card UI
55. Stop the game
56. Replace the Edwin card with the Tirion card in the Card slot
57. Press Play again
58. The card should now display Tirion's information instead
Success! You can now easily swap between different cards simply by
changing which Scriptable Object is assigned. No code changes required!
Part 7: Working with Multiple Cards
7.1 Duplicate the Card GameObject
59. Select your card GameObject in the Hierarchy
60. Press Ctrl+D (Cmd+D on Mac) to duplicate it
61. Position the two cards side by side using the Rect Transform
62. Select the first card and assign the Edwin Scriptable Object
63. Select the second card and assign the Tirion Scriptable Object
7.2 Test Multiple Cards
64. Press Play
65. Both cards should display simultaneously with their respective data
66. Notice how easy it is to display multiple cards using the same display system
Key Observations:
• Each card GameObject uses the same CardDisplay script
• Each displays different data based on which Scriptable Object is assigned
• The Scriptable Objects are extremely lightweight (only 1 KB each)
• Changes to Scriptable Objects can be made while the game is running
• The same Scriptable Object can be referenced by multiple GameObjects
Expected Results
Upon successful completion of this lab, you should have:
67. A Card Scriptable Object template that defines the structure for card data
68. At least two card instances (Edwin and Tirion) with unique properties
69. A functional CardDisplay script that reads Scriptable Object data
70. UI elements that dynamically display card information
71. The ability to easily swap between different cards without code modification
72. Understanding of how Scriptable Objects improve game data management
Visual Confirmation:
When you press Play, each card should correctly display its name, description,
artwork, mana cost, attack value, and health value. The data should match what you
entered in the Scriptable Object assets. You should be able to create additional
cards and display them instantly without any additional coding.
Common Issues and Solutions
Issue 1: 'Card' option not appearing in Create menu
• Solution: Make sure you saved the [Link] script and Unity has finished
compiling
• Check that the CreateAssetMenu attribute is spelled correctly
Issue 2: NullReferenceException when playing
• Solution: Ensure all UI references are assigned in the Inspector
• Make sure a Scriptable Object is assigned to the Card slot
Issue 3: Card data not displaying correctly
• Solution: Verify that the correct UI elements are dragged into the correct slots
• Check that the UI Text and Image components exist on the child objects
Issue 4: Artwork not displaying
• Solution: Make sure your images are imported as Sprites (not Textures)
• Check that a sprite is assigned to the artwork field in the Scriptable Object
Discussion Questions
73. Why are Scriptable Objects more efficient than using prefabs for storing data?
74. What advantages does the CreateAssetMenu attribute provide?
75. How does using Scriptable Objects promote code reusability?
76. In what scenarios would Scriptable Objects be preferable to storing data in a
database?
77. How could you extend the Card system to include special abilities or effects?
78. What is the difference between inheriting from MonoBehaviour versus
ScriptableObject?
79. How might Scriptable Objects be used in a multiplayer game?
80. What are the limitations of Scriptable Objects, and when should you not use
them?
Extension Exercises
Exercise 1: Card Rarity System
Add a rarity system to your cards:
• Create an enum for card rarities (Common, Rare, Epic, Legendary)
• Add a rarity field to the Card Scriptable Object
• Modify CardDisplay to change the card's border color based on rarity
Exercise 2: Card Effects
Implement special card effects:
• Add a string field for special abilities (e.g., 'Taunt', 'Divine Shield')
• Create an icon system to display these abilities on the card
• Implement methods in the Card class that execute these effects
Exercise 3: Dynamic Card Generation
Create a system that generates cards at runtime:
• Write a CardGenerator script that creates Scriptable Objects programmatically
• Randomize card stats within balanced ranges
• Create a UI button that spawns a new random card
Exercise 4: Card Collection System
Build a card collection manager:
• Create a CardCollection Scriptable Object that stores a list of Card references
• Implement methods to add, remove, and search for cards
• Create a UI system to browse and display all cards in the collection
Exercise 5: Card Animation System
Add polish with animations:
• Implement hover effects when the mouse is over a card
• Create a card flip animation when switching between different cards
• Add particle effects for rare or legendary cards
Best Practices for Scriptable Objects
Organization
• Create dedicated folders for Scriptable Objects (e.g.,
Assets/ScriptableObjects/Cards)
• Use descriptive names for your Scriptable Object assets
• Group related Scriptable Objects in subfolders
Design Principles
• Keep Scriptable Objects focused on data storage, not game logic
• Use inheritance to create specialized types (e.g., WeaponCard : Card)
• Consider using events or UnityEvents for callbacks instead of direct
references
• Document your Scriptable Objects with comments and tooltip attributes
Performance Considerations
• Scriptable Objects are loaded into memory when first accessed
• Use [Link]() to free memory if needed
• Consider using AssetBundles for large collections of Scriptable Objects
• Avoid storing references to scene objects in Scriptable Objects
Testing and Debugging
• Use the [SerializeField] attribute for private fields you want to edit in the
Inspector
• Implement OnValidate() to validate data when values change in the Inspector
• Create custom editors for complex Scriptable Objects
• Remember that Scriptable Objects persist between play sessions in the Editor
Conclusion
Scriptable Objects are a fundamental tool in Unity development that enable efficient
data management and modular design. Through this lab, you have learned how to
create reusable data containers, reference them in your scripts, and display their
information in the game. This pattern is essential for creating scalable games with
large amounts of content.
The techniques you've learned can be applied to countless scenarios beyond card
games - from inventory systems and enemy databases to configuration files and
audio management. As you continue developing games, you'll find Scriptable
Objects to be an indispensable part of your toolkit.
Key Takeaways
• Scriptable Objects separate data from logic, promoting clean architecture
• They are extremely lightweight and memory efficient
• The CreateAssetMenu attribute makes them easy to create and manage
• Multiple objects can reference the same Scriptable Object
• They can contain both data and methods
• Scriptable Objects make it easy to create content without programming
Further Learning
To deepen your understanding of Scriptable Objects, consider exploring:
• Unity's official documentation on Scriptable Objects
• Advanced patterns like Scriptable Object Events and Architectures
• Creating custom editors for Scriptable Objects
• Using Scriptable Objects with Unity's Addressables system
• Implementing data persistence with Scriptable Objects
• Building entire game architectures around Scriptable Objects
Appendix A: Complete Code Listings
[Link] - Complete Script
using UnityEngine;
[CreateAssetMenu(fileName = "New Card", menuName = "Card")]
public class Card : ScriptableObject
{
public new string name;
public string description;
public Sprite artwork;
public int manaCost;
public int attack;
public int health;
public void Print()
{
[Link](name + ": " + description + ". The card costs " +
manaCost);
}
}
[Link] - Complete Script
using UnityEngine;
using [Link];
public class CardDisplay : MonoBehaviour
{
public Card card;
public Text nameText;
public Text descriptionText;
public Image artworkImage;
public Text manaText;
public Text attackText;
public Text healthText;
void Start()
{
[Link] = [Link];
[Link] = [Link];
[Link] = [Link];
[Link] = [Link]();
[Link] = [Link]();
[Link] = [Link]();
}
}
Appendix B: Additional Resources
Official Unity Documentation
• Unity Manual: Scriptable Objects
• Unity Scripting API: ScriptableObject
• Unity Learn: Introduction to Scriptable Objects
Recommended Tutorials
• Unity's Game Architecture with Scriptable Objects
• Advanced Scriptable Object Patterns
• Creating Editor Tools for Scriptable Objects
Community Resources
• Unity Forums: Scriptable Objects Discussion
• GitHub: Open-source Scriptable Object frameworks
• Unity Asset Store: Scriptable Object utilities
Glossary
Scriptable Object:
A data container class in Unity that exists as an asset file, independent of
GameObjects in scenes.
MonoBehaviour:
The base class from which every Unity script derives by default. Used for
components attached to GameObjects.
Inspector:
Unity's window for viewing and editing properties of selected GameObjects and
assets.
Prefab:
A reusable GameObject template that can be instantiated multiple times in scenes.
Attribute:
Metadata tags in C# that provide additional information about classes, methods, or
properties.
Sprite:
A 2D graphic object used in Unity's 2D features and UI system.
Canvas:
The area in which all UI elements are placed and rendered in Unity.
End of Lab Manual