SlideShare a Scribd company logo
Save System in
Garden of the Sea
Amanda Rösler
Neat Corporation
November 2020
How to save the state of an open-ended
gardening & exploration game in Unity
Introduction
● Lives in Sweden
● Have worked in game industry
since 2011
● Lead programmer on an indie
game called Garden of the Sea
Neat Corporation
● Indie studio in Stockholm
● 11 employees
● Makes VR games
● Budget Cuts 1 & 2
● Garden on the Sea
Save System in Garden of the Sea: How to save the state of an open-ended gardening & exploration game in Unity / Amanda Rösler (Neat Corporation)
Garden of the Sea
● Made in Unity
● Early access on Steam
● Gardening, crafting, fishing,
trading, quests, animals, etc
● Traveling to multiple islands
Challenges
● Large world where areas need to
stream in & out
● Lots of dynamic objects
● Lots of different types of game objects
● Players can create and destroy objects
● How do you save the game state?!?
Old Save System
● Code ported from Budget Cuts
● List of added & removed objects in
save file
● Remove objects from scene after it
was loaded + spawn new ones
● Not the best solution for this game
New Save System
● Not just a save system...
○ Spawn manager
○ System for initializing components
○ Streaming in new areas
Scene Handling
● Everything was in one
big scene
scene
Scene Handling
● Everything was in one
big scene
● Split the scene so that
each area/island was
in its own scene
Scene Handling
● Split each island into two
additional parts:
static dynamic
● One “static” scene
● One “dynamic” scene
● Static meshes
● Quests
● Spawn points
● Characters
● Etc
Static Scene
Plants, crafted items, wood
logs & other resources
= Everything that can be
removed from the scene
Dynamic Scene
Why?
Two reasons:
1. Spawn all the dynamic objects
separately, instead of loading the
“dynamic” scene
2. Stream in the static scene further
away from the player
How to Serialize a Reference to a Prefab?
● Serialize path and load with Resources.Load()?
○ Doesn’t work if you move/rename the prefab!
● Serialize GUID from the AssetDatabase?
○ Can’t use AssetDatabase during runtime!
● Package provided by Unity
● Easy way to load assets asynchronously
● Each asset is identified by a GUID and and address
○ Address can be changed by user
○ GUID is persistent
Addressable Assets System
● Asset can be loaded by address or GUID in runtime
● To load by GUID, you need an AssetReference
○ Created from the GUID
○ … or by assigning an asset to it in the inspector
Addressable Assets System
Save System in Garden of the Sea: How to save the state of an open-ended gardening & exploration game in Unity / Amanda Rösler (Neat Corporation)
SaveObject Component
using UnityEngine.Addressables;
public class SaveObject : MonoBehaviour {
SaveID id; // unique 128-bit id
AssetReference prefab; // prefab to load
Saveable[] saveables; // Grabbable, etc
...
Save File Structure
Dynamic Objects
Static Objects
Saveable Data
SaveID
AssetReference
Transform
SaveID
Transform
SaveID
SaveableType
SaveableState
JSON
Soil data
BINARY
Saveable & SaveableState
● All components that need to save some data
inherit from Saveable
● Need to implement CreateState() which
returns a SaveableState
● SaveableState should contain serializable data
(that can be converted to JSON)
Example: WateringCan
public class WateringCan : Saveable {
public override WaterState CreateState(){
float amount = GetWaterAmount();
return new WaterState( amount );
}
} Inherits from SaveableState!
Example: WateringCan
public class WaterState : SaveableState {
public float waterAmount = 0.0f;
public WaterState(float a) {
waterAmount = a;
}
}
SaveID: 1234,
SaveableType: WateringCan,
SaveableState:
{waterAmount: 0.8f}
Example: WateringCan
public abstract class Saveable : MonoBehavior {
SaveableState state = null;
void InitState(SaveableState s = null) {
if (s == null) state = CreateState();
else state = s;
}
...
Example: WateringCan
public class WateringCan : Saveable {
public void Initialize() {
WaterState s = state as WaterState;
SetWaterAmount(s.waterAmount);
}
...
Initialization Flow - New Game
1. Load static scenes
3. Call InitState() on all Saveables,
which will in turn call CreateState()
2. Load dynamic scenes
4. Call Initialize() on all Saveables
static
dynamic
Initialization Flow - Load Save File
1. Read save file data
2. Load static scenes
3. Spawn dynamic objects
4. Call InitState(state) on all Saveables and pass in
the SaveableState from the save file data
5. Call Initialize() on all Saveables
static
Initialization Flow - Reasons
● When Initialize() is called, it’s guaranteed that the object
has been assigned its initial data
● Have all initialization logic in one place
● Guaranteed that all objects in the same area have spawned
● Possible to specify the order in which different types of
Saveables are initialized
JSON vs Custom Binary Format
public void Save( SaveDataSerializer data ) {
data.Serialize( isInInventory );
data.Serialize( hasBeenUnlocked );
}
public void Load( ParsedSaveComponent data ) {
isInInventory = bool.Parse( data.data[0] );
hasBeenUnlocked = bool.Parse( data.data[1] );
}
JSON vs Custom Binary Format
● When using JSON, the SaveableState can be
converted directly to JSON and back again
SaveableState state = someObject.CreateState();
string json = JsonUtility.ToJson( state );
state = JsonUtility.FromJson( json, SaveableState );
JSON vs Custom Binary Format
● It even works if you add or remove a member variable
from the SaveableState
● Easier to maintain compatibility with save files from
older versions
● Human-readable
JSON vs Custom Binary Format
● Drawback: JSON is slow and can result in larger
save files
● Converting to/from JSON: around 40 ms for
700 objects
● File size: 2 mb of JSON + additional 3 mb of
binary data for the soil/ground state
Streaming In New Areas
● When the player goes to a new
area, the previous area will be
unloaded
● Need to save the state of the
previous area before it’s unloaded
Streaming In New Areas
● Save data for each area is
stored separately
● Keeps track of which areas
are currently loaded and
which objects belong to
which area
Area 1
Area 2
Moving Items Between Areas
● Scenario: player brings an item
from one island to another one
○ Need to move the game object
to the other scene
○ Need to associate the save
data with the correct area
Area 1
Area 2
Future Improvements
● Performance when saving
● System for saving incrementally over several frames
● JSON conversion on a background thread?
● Replace JSON with BSON or other binary format?
● Compressing the save file?
Thanks for listening!
neatcorporation.com
twitter.com/neatcorp
linkedin.com/in/amandarosler
twitter.com/mandyrosler

More Related Content

PDF
Geolocation in mongodb
PPTX
World wind java sdk in progess
PDF
State of GeoServer 2.13
PDF
Geolocation in MongoDB
PDF
Creating Ext GWT Extensions and Components
PDF
Александр Терещук - Memory Analyzer Tool and memory optimization tips in Android
PDF
GeoServer Ecosystem 2018
PDF
GeoServer Orientation
Geolocation in mongodb
World wind java sdk in progess
State of GeoServer 2.13
Geolocation in MongoDB
Creating Ext GWT Extensions and Components
Александр Терещук - Memory Analyzer Tool and memory optimization tips in Android
GeoServer Ecosystem 2018
GeoServer Orientation

Similar to Save System in Garden of the Sea: How to save the state of an open-ended gardening & exploration game in Unity / Amanda Rösler (Neat Corporation) (20)

PPTX
OGDC 2014: Architecting Games in Unity
PDF
Optimizing Large Scenes in Unity
PDF
OGDC 2014_Architecting Games in Unity_Mr. Rustum Scammell
PPTX
Game object models - Game Engine Architecture
PPTX
Cross-scene references: A shock to the system - Unite Copenhagen 2019
PPTX
Extending unity3D Editor
PPTX
Unity - Internals: memory and performance
PPTX
98 374 Lesson 06-slides
PPTX
Optimizing mobile applications - Ian Dundore, Mark Harkness
PPTX
Tales from the Optimization Trenches - Unite Copenhagen 2019
PPTX
Speed up your asset imports for big projects - Unite Copenhagen 2019
PDF
The Hack Spectrum: Tips, Tricks, and Hacks for Unity
PPTX
Bringing Supernatural Thriller, "Oxenfree" to Nintendo Switch
PPTX
Creating great Unity games for Windows 10 - Part 1
PDF
My 10 days with Phaser.js - WarsawJS Meetup #13
PDF
Eight Rules for Making Your First Great Game
PDF
intern.pdf
PPTX
Cloud-Based Dynamic Streaming and Loading of 3D Scene
PDF
Unity Internals: Memory and Performance
OGDC 2014: Architecting Games in Unity
Optimizing Large Scenes in Unity
OGDC 2014_Architecting Games in Unity_Mr. Rustum Scammell
Game object models - Game Engine Architecture
Cross-scene references: A shock to the system - Unite Copenhagen 2019
Extending unity3D Editor
Unity - Internals: memory and performance
98 374 Lesson 06-slides
Optimizing mobile applications - Ian Dundore, Mark Harkness
Tales from the Optimization Trenches - Unite Copenhagen 2019
Speed up your asset imports for big projects - Unite Copenhagen 2019
The Hack Spectrum: Tips, Tricks, and Hacks for Unity
Bringing Supernatural Thriller, "Oxenfree" to Nintendo Switch
Creating great Unity games for Windows 10 - Part 1
My 10 days with Phaser.js - WarsawJS Meetup #13
Eight Rules for Making Your First Great Game
intern.pdf
Cloud-Based Dynamic Streaming and Loading of 3D Scene
Unity Internals: Memory and Performance
Ad

More from DevGAMM Conference (20)

PPTX
The art of small steps, or how to make sound for games in conditions of war /...
PPTX
Breaking up with FMOD - Why we ended things and embraced Metasounds / Daniel ...
PPTX
How Audio Objects Improve Spatial Accuracy / Mads Maretty Sønderup (Audiokine...
PPTX
Why indie developers should consider hyper-casual right now / Igor Gurenyov (...
PPTX
AI / ML for Indies / Tyler Coleman (Retora Games)
PDF
Agility is the Key: Power Up Your GameDev Project Management with Agile Pract...
PPTX
New PR Tech and AI Tools for 2023: A Game Changer for Outreach / Kirill Perev...
PDF
Playable Ads - Revolutionizing mobile games advertising / Jakub Kukuryk (Popc...
PDF
Creative Collaboration: Managing an Art Team / Nastassia Radzivonava (Glera G...
PDF
From Local to Global: Unleashing the Power of Payments / Jan Kuhlmannn (Xsolla)
PDF
Strategies and case studies to grow LTV in 2023 / Julia Iljuk (Balancy)
PDF
Why is ASO not working in 2023 and how to change it? / Olena Vedmedenko (Keya...
PDF
How to increase wishlists & game sales from China? Growth marketing tactics &...
PDF
Turkish Gaming Industry and HR Insights / Mustafa Mert EFE (Zindhu)
PDF
Building an Awesome Creative Team from Scratch, Capable of Scaling Up / Sasha...
PPTX
Seven Reasons Why Your LiveOps Is Not Performing / Alexander Devyaterikov (Be...
PDF
The Power of Game and Music Collaborations: Reaching and Engaging the Masses ...
PPTX
Branded Content: How to overcome players' immunity to advertising / Alex Brod...
PPTX
Resurrecting Chasm: The Rift - A Source-less Remastering Journey / Gennadii P...
PPTX
How NOT to do showcase events: Behind the scenes of Midnight Show / Andrew Ko...
The art of small steps, or how to make sound for games in conditions of war /...
Breaking up with FMOD - Why we ended things and embraced Metasounds / Daniel ...
How Audio Objects Improve Spatial Accuracy / Mads Maretty Sønderup (Audiokine...
Why indie developers should consider hyper-casual right now / Igor Gurenyov (...
AI / ML for Indies / Tyler Coleman (Retora Games)
Agility is the Key: Power Up Your GameDev Project Management with Agile Pract...
New PR Tech and AI Tools for 2023: A Game Changer for Outreach / Kirill Perev...
Playable Ads - Revolutionizing mobile games advertising / Jakub Kukuryk (Popc...
Creative Collaboration: Managing an Art Team / Nastassia Radzivonava (Glera G...
From Local to Global: Unleashing the Power of Payments / Jan Kuhlmannn (Xsolla)
Strategies and case studies to grow LTV in 2023 / Julia Iljuk (Balancy)
Why is ASO not working in 2023 and how to change it? / Olena Vedmedenko (Keya...
How to increase wishlists & game sales from China? Growth marketing tactics &...
Turkish Gaming Industry and HR Insights / Mustafa Mert EFE (Zindhu)
Building an Awesome Creative Team from Scratch, Capable of Scaling Up / Sasha...
Seven Reasons Why Your LiveOps Is Not Performing / Alexander Devyaterikov (Be...
The Power of Game and Music Collaborations: Reaching and Engaging the Masses ...
Branded Content: How to overcome players' immunity to advertising / Alex Brod...
Resurrecting Chasm: The Rift - A Source-less Remastering Journey / Gennadii P...
How NOT to do showcase events: Behind the scenes of Midnight Show / Andrew Ko...
Ad

Recently uploaded (20)

PPTX
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
PDF
MCP Security Tutorial - Beginner to Advanced
PDF
Autodesk AutoCAD Crack Free Download 2025
PDF
Microsoft Office 365 Crack Download Free
PPTX
Cybersecurity: Protecting the Digital World
PDF
CCleaner 6.39.11548 Crack 2025 License Key
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
Weekly report ppt - harsh dattuprasad patel.pptx
PPTX
CNN LeNet5 Architecture: Neural Networks
PPTX
"Secure File Sharing Solutions on AWS".pptx
PPTX
Patient Appointment Booking in Odoo with online payment
PPTX
Tech Workshop Escape Room Tech Workshop
PDF
Website Design Services for Small Businesses.pdf
PDF
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
PDF
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
PDF
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
PDF
Cost to Outsource Software Development in 2025
AMADEUS TRAVEL AGENT SOFTWARE | AMADEUS TICKETING SYSTEM
Wondershare Recoverit Full Crack New Version (Latest 2025)
MCP Security Tutorial - Beginner to Advanced
Autodesk AutoCAD Crack Free Download 2025
Microsoft Office 365 Crack Download Free
Cybersecurity: Protecting the Digital World
CCleaner 6.39.11548 Crack 2025 License Key
DNT Brochure 2025 – ISV Solutions @ D365
Advanced SystemCare Ultimate Crack + Portable (2025)
Computer Software and OS of computer science of grade 11.pptx
Weekly report ppt - harsh dattuprasad patel.pptx
CNN LeNet5 Architecture: Neural Networks
"Secure File Sharing Solutions on AWS".pptx
Patient Appointment Booking in Odoo with online payment
Tech Workshop Escape Room Tech Workshop
Website Design Services for Small Businesses.pdf
How AI/LLM recommend to you ? GDG meetup 16 Aug by Fariman Guliev
Product Update: Alluxio AI 3.7 Now with Sub-Millisecond Latency
EaseUS PDF Editor Pro 6.2.0.2 Crack with License Key 2025
Cost to Outsource Software Development in 2025

Save System in Garden of the Sea: How to save the state of an open-ended gardening & exploration game in Unity / Amanda Rösler (Neat Corporation)

  • 1. Save System in Garden of the Sea Amanda Rösler Neat Corporation November 2020 How to save the state of an open-ended gardening & exploration game in Unity
  • 2. Introduction ● Lives in Sweden ● Have worked in game industry since 2011 ● Lead programmer on an indie game called Garden of the Sea
  • 3. Neat Corporation ● Indie studio in Stockholm ● 11 employees ● Makes VR games ● Budget Cuts 1 & 2 ● Garden on the Sea
  • 5. Garden of the Sea ● Made in Unity ● Early access on Steam ● Gardening, crafting, fishing, trading, quests, animals, etc ● Traveling to multiple islands
  • 6. Challenges ● Large world where areas need to stream in & out ● Lots of dynamic objects ● Lots of different types of game objects ● Players can create and destroy objects ● How do you save the game state?!?
  • 7. Old Save System ● Code ported from Budget Cuts ● List of added & removed objects in save file ● Remove objects from scene after it was loaded + spawn new ones ● Not the best solution for this game
  • 8. New Save System ● Not just a save system... ○ Spawn manager ○ System for initializing components ○ Streaming in new areas
  • 9. Scene Handling ● Everything was in one big scene scene
  • 10. Scene Handling ● Everything was in one big scene ● Split the scene so that each area/island was in its own scene
  • 11. Scene Handling ● Split each island into two additional parts: static dynamic ● One “static” scene ● One “dynamic” scene
  • 12. ● Static meshes ● Quests ● Spawn points ● Characters ● Etc Static Scene
  • 13. Plants, crafted items, wood logs & other resources = Everything that can be removed from the scene Dynamic Scene
  • 14. Why? Two reasons: 1. Spawn all the dynamic objects separately, instead of loading the “dynamic” scene 2. Stream in the static scene further away from the player
  • 15. How to Serialize a Reference to a Prefab? ● Serialize path and load with Resources.Load()? ○ Doesn’t work if you move/rename the prefab! ● Serialize GUID from the AssetDatabase? ○ Can’t use AssetDatabase during runtime!
  • 16. ● Package provided by Unity ● Easy way to load assets asynchronously ● Each asset is identified by a GUID and and address ○ Address can be changed by user ○ GUID is persistent Addressable Assets System
  • 17. ● Asset can be loaded by address or GUID in runtime ● To load by GUID, you need an AssetReference ○ Created from the GUID ○ … or by assigning an asset to it in the inspector Addressable Assets System
  • 19. SaveObject Component using UnityEngine.Addressables; public class SaveObject : MonoBehaviour { SaveID id; // unique 128-bit id AssetReference prefab; // prefab to load Saveable[] saveables; // Grabbable, etc ...
  • 20. Save File Structure Dynamic Objects Static Objects Saveable Data SaveID AssetReference Transform SaveID Transform SaveID SaveableType SaveableState JSON Soil data BINARY
  • 21. Saveable & SaveableState ● All components that need to save some data inherit from Saveable ● Need to implement CreateState() which returns a SaveableState ● SaveableState should contain serializable data (that can be converted to JSON)
  • 22. Example: WateringCan public class WateringCan : Saveable { public override WaterState CreateState(){ float amount = GetWaterAmount(); return new WaterState( amount ); } } Inherits from SaveableState!
  • 23. Example: WateringCan public class WaterState : SaveableState { public float waterAmount = 0.0f; public WaterState(float a) { waterAmount = a; } } SaveID: 1234, SaveableType: WateringCan, SaveableState: {waterAmount: 0.8f}
  • 24. Example: WateringCan public abstract class Saveable : MonoBehavior { SaveableState state = null; void InitState(SaveableState s = null) { if (s == null) state = CreateState(); else state = s; } ...
  • 25. Example: WateringCan public class WateringCan : Saveable { public void Initialize() { WaterState s = state as WaterState; SetWaterAmount(s.waterAmount); } ...
  • 26. Initialization Flow - New Game 1. Load static scenes 3. Call InitState() on all Saveables, which will in turn call CreateState() 2. Load dynamic scenes 4. Call Initialize() on all Saveables static dynamic
  • 27. Initialization Flow - Load Save File 1. Read save file data 2. Load static scenes 3. Spawn dynamic objects 4. Call InitState(state) on all Saveables and pass in the SaveableState from the save file data 5. Call Initialize() on all Saveables static
  • 28. Initialization Flow - Reasons ● When Initialize() is called, it’s guaranteed that the object has been assigned its initial data ● Have all initialization logic in one place ● Guaranteed that all objects in the same area have spawned ● Possible to specify the order in which different types of Saveables are initialized
  • 29. JSON vs Custom Binary Format public void Save( SaveDataSerializer data ) { data.Serialize( isInInventory ); data.Serialize( hasBeenUnlocked ); } public void Load( ParsedSaveComponent data ) { isInInventory = bool.Parse( data.data[0] ); hasBeenUnlocked = bool.Parse( data.data[1] ); }
  • 30. JSON vs Custom Binary Format ● When using JSON, the SaveableState can be converted directly to JSON and back again SaveableState state = someObject.CreateState(); string json = JsonUtility.ToJson( state ); state = JsonUtility.FromJson( json, SaveableState );
  • 31. JSON vs Custom Binary Format ● It even works if you add or remove a member variable from the SaveableState ● Easier to maintain compatibility with save files from older versions ● Human-readable
  • 32. JSON vs Custom Binary Format ● Drawback: JSON is slow and can result in larger save files ● Converting to/from JSON: around 40 ms for 700 objects ● File size: 2 mb of JSON + additional 3 mb of binary data for the soil/ground state
  • 33. Streaming In New Areas ● When the player goes to a new area, the previous area will be unloaded ● Need to save the state of the previous area before it’s unloaded
  • 34. Streaming In New Areas ● Save data for each area is stored separately ● Keeps track of which areas are currently loaded and which objects belong to which area Area 1 Area 2
  • 35. Moving Items Between Areas ● Scenario: player brings an item from one island to another one ○ Need to move the game object to the other scene ○ Need to associate the save data with the correct area Area 1 Area 2
  • 36. Future Improvements ● Performance when saving ● System for saving incrementally over several frames ● JSON conversion on a background thread? ● Replace JSON with BSON or other binary format? ● Compressing the save file?