Devlog: The Great Refactor – Taming Scriptable Objects for a Robust Save System
Ahoy, fellow Dwarves!
Today, I want to take you on a deep dive into the engine room of Into The Deep. While I’ve been busy forging the levels for Act 1, a huge effort has been underway in the background: a complete and critical refactoring of the game’s core architecture, specifically how it handles and saves your progress.
The Glorious Trap of Scriptable Objects
Anyone who has worked with Unity loves ScriptableObjects (SOs). They are a blessing for prototyping. You can create data containers as assets, drag-and-drop references in the Inspector, and everything just works. It’s wonderfully simple.
My initial approach for save games was built entirely on this structure. I had a PlayerData SO, which held a reference to a CrewSO, which in turn held references to CharacterSOs. When Amos took damage during a playtest, my code would simply change the health value directly inside the Amos_CharacterSO asset. Convenient? Absolutely. A good long-term idea? Not so much.
I had walked right into the classic trap: I was using SOs, which should be templates, as storage for mutable runtime data. It’s like building a house and then drawing on the original blueprint with a marker to show where you put your couch. The next time you use that blueprint, you’ll be wondering why there’s a couch already drawn on it.
The Cracks in the Foundation
This approach worked for a quick demo, but as I started building a real game, the problems became glaringly obvious:
- “Dirty” Project Assets: This was the biggest headache. If Amos died in Play Mode and his health was set to 0 in the SO, it stayed at 0 after I exited Play Mode. I had to manually reset my project data constantly to get a clean test run. This is error-prone and incredibly annoying.
- No Multiple Save Slots: How could I possibly manage three separate save files when they all reference and modify the exact same CharacterSO assets? It’s impossible. Each save would effectively overwrite the state of the others.
- The Serialization Dilemma: To save a game to a file (like a .json), you need to serialize your data. Unity’s JsonUtility can only serialize simple data types (strings, ints, floats, etc.). It has no idea how to convert a direct reference to a project asset like a ScriptableObject into text. That reference is just a “pointer” inside the engine; in a text file, it’s meaningless.
It was clear: the system had to be rebuilt from the ground up.
The Solution: The Great Separation of Template and State
The new system is built on one fundamental principle: a strict separation between Template Data (the blueprint) and State Data (the current save game).
1. The Blueprint (Template):
My ScriptableObjects (CharacterSO, WeaponSO, etc.) are now treated as pure, read-only templates. They only contain the base values: a character’s name, their maximum health, a weapon’s base damage. They are never modified by code during runtime.
// CharacterSO.cs - The Template (Read-Only)
[CreateAssetMenu]
public class CharacterSO : ScriptableObject
{
public string characterID; // e.g., "amos_eisenfaust"
public string characterName;
public float maxHealth;
// ...other base stats...
}
2. The State (Instance):
For the data that changes, I’ve created new, simple C# classes (often called POCOs) that don’t inherit from anything and just hold data.
- CharacterState: Stores only what changes for a character, like currentLevel, currentXP, currentHP.
- GameSaveData: This is the main container for a complete save file. It holds lists of these State objects (e.g., List<CharacterState> squadStates).
The crucial trick is that these State classes don’t store direct references to the SO assets. Instead, they only store a simple string ID. So, Amos’s CharacterState doesn’t contain the Amos_CharacterSO asset, it just contains the string “amos_eisenfaust”.
// CharacterState.cs - The Saved Data
[System.Serializable]
public class CharacterState
{
public string templateID; // The "link" back to the CharacterSO
public float currentHP;
public int currentLevel;
// ...other dynamic data...
}
How It All Works: IDs and The Database
To make this work, I created a central GameAssetDatabase. This is a single ScriptableObject that holds references to all my template SOs (characters, weapons, levels, etc.).
The new save/load flow looks like this:
- Saving: A DataManager collects all the State objects (from all characters, quests, etc.), bundles them into a single GameSaveData object, and serializes it into a JSON file. The string IDs can be saved perfectly.
- Loading: The DataManager reads the JSON file and reconstructs the GameSaveData object in memory.
- Instantiating: A SquadManager looks at the list of loaded CharacterState objects. For each one, it takes the templateID (e.g., “amos_eisenfaust”), goes to the GameAssetDatabase and asks, “Give me the CharacterSO with this ID.” Once it has the template, it spawns the character’s prefab and applies the loaded state (currentHP, Level, etc.) to it.
This pattern of separating data and referencing assets via IDs wasn’t entirely new to me. My previous explorations into multiplayer with Netcode for Gameobjects use a very similar approach, as you can’t send complex object references over the network—only serializable data like IDs. That experience really taught me to appreciate this robust, decoupled architecture.
The Best of Both Worlds: Making Testing Easy Again
The biggest drawback of this clean system is losing the convenience of setting up test scenarios in the Inspector. I can no longer just drag a “Test_Savegame_SO” into a manager.
My solution is an Editor-only tool. I’ve created a special SaveFilePresetSO that only exists inside the Unity Editor. Here, I can drag-and-drop CharacterSOs, set test values (Level 5, 1000 gold, etc.) just like before. A custom button in the Inspector, “Generate JSON Save File”, then converts this preset into a clean, loadable .json save file.
// SaveFilePresetSO.cs - An Editor-Only Tool
[CreateAssetMenu]
public class SaveFilePresetSO : ScriptableObject
{
[Header("Test-Setup")]
public int saveSlotIndex = 99;
public int currency = 1000;
public List<CharacterPreset> crewRoster; // Can drag CharacterSOs in here!
// ...
}
[System.Serializable]
public class CharacterPreset
{
public CharacterSo characterTemplate; // Direct SO reference for editor convenience
public int level = 5;
}
This gives me the old convenience without compromising the clean runtime architecture.
The Moral of the Story
If there’s a lesson here, it’s this: Refactor sooner rather than later. The initial comfort of a “hacky” prototyping solution creates a massive “technical debt”. Unraveling that architecture later is an enormous and sometimes frustrating task, as it touches almost every single system in the game.
But there’s a silver lining: being forced to go through every class, from CharacterUnit to GameManager, also gives you a unique opportunity to clean up, improve, and solidify your entire codebase. It’s safe to say this ID-based architecture will be my standard practice for all future projects. The days of using ScriptableObjects for dynamic data are definitely over!
Thanks for reading!
Tobi
Into The Deep – Full Focus on Act 1!
Ahoy, fellow Dwarves!
For decades, our people have wandered in exile since the fall of our great mountain-home, Ølheim. But now, the time has come to reclaim it!
Amos – King of Ølheim
Thank you for your support and for being part of this community. It’s time to give you a more detailed look behind the curtain and share our plans for Into The Deep, with a full focus on Act 1 of the game. Our goal is to forge a rich, tactical experience, and your feedback is the fuel that keeps our smithing fires burning!
Heading into Production!
I’m happy to announce that after countless hours of hard work, the foundational gameplay systems (like combat, movement, and squad mechanics) are now “largely” in place (who am I kidding?). This means we are officially moving into the production phase!

Our main focus from now on will be on level design – crafting the exciting, challenging, and story-rich missions of Act 1. Alongside this, I’ll be developing the cool new features that round out the experience, like the evolving Camp and the introduction of NPC traders.
This plan is our blueprint for turning the core gameplay into a full-fledged adventure.
Gameplay Philosophy
My biggest inspiration is the fantastic gameplay of games like SteamWorld Heist. The development is committed to these core principles:
- Tactical, Skill-Based Combat: Every shot counts with a manual aiming system with a reliable trajectory. This will allow for skill shots and ricochets! Using the environment to your advantage will be crucial. But better stay in cover!
- Squad: You won’t just be controlling generic soldiers. Every character you recruit, starting with Amos and Glimra, will have unique starting abilities and skill trees. Your choice of squad members will have a real impact on your strategy in each mission.
- Customization: Finding loot is exciting! You’ll discover a wide variety of weapons and utility items (like grenades and buff potions). Equipping your squad for the upcoming mission is a huge part of the fun.
- Progression: Your efforts will be visible. I want to create a clear sense of progression, not just for your characters, but for your base of operations. The camp will evolve from a few tents into a lively hub, showing your journey.
The Journey Through Act 1: The Mine
Your quest begins with a single goal: to find a way back into the lost city and take the first steps towards fulfilling an old prophecy that promises to restore the dwarven spirit.

Act 1 is designed to be a complete, self-contained adventure that forms the foundation for the rest of the game. Our plan is to build 5 main, handcrafted levels that will guide you through the story of Act 1, from your first steps into the darkness to a dramatic final confrontation. For all you explorers out there, I’m also planning to sprinkle in optional side-missions and hidden secrets for you to discover. Each level will introduce new challenges and story elements.
The Camp: Your Growing Home
Your base of operations evolves with you!
- Phase 1: You’ll start in a rudimentary camp on the surface, with just a few tents and a campfire.
- Phase 2: By the end of Act 1, you’ll establish a proper operational base down in the mine’s tavern. This will be a lively hub where you can see the dwarves you’ve rescued.
- NPCs with a Purpose: Rescued characters will offer services!
- The Brewer: A legendary master craftsman, said to be the last dwarf who knows the recipe for the famed Ølheimer brew. He’s key to fulfilling the prophecy and can create powerful buff potions and healing items for your team.
- The Trader: A resourceful dwarf who will buy your excess loot and sell essential supplies.
- more to be announced
A Word from a Solo Developer
Into The Deep is a passion project developed by just one person – me! This is a massive undertaking, and bringing this world to life is both a challenge and a joy.
I also want to be transparent with you all. I had to scale back my output over the last few months as I was getting close to burnout trying to juggle my day job, family, and game development. It’s a tough balance! However, I’ve found a better rhythm now and am back to making slow but consistent progress. I’ll also do my best to post more frequent updates and automatically generated changelogs, which you can follow in our new Changelog Section.
My primary goal is to build a cool, polished, and complete short adventure for you to enjoy. This means I have to be smart about which features make it into the initial release. While I have a vision for the game, my focus is on delivering a higher-quality core experience first.
The biggest problems are graphical assets. If I would do anything on my own, it would add years to my development schedule, so I’m glad that I can buy much of the stuff I use. This may lead to a bit of inconsistent experience. But I hope my eye as a designer and product manager will enable me to set this off a bit.
Focusing on a “Guiding Thread”
There is a German expression that describes exactly what was missing in the development phase. A “red thread” – a thread that holds everything together and makes it coherent, that indicates the direction like the North Star. I think I’ve found it now by defining the basic story and plot. Now I can weigh every decision against it. Now that I have it, I feel motivated to finally tackle the levels and take care of the design.

I think that will be a point that will be at the top of the post mortem of this project, and it really would have saved me a lot of frustration. My nature tends to say “make it quick and try it out”, and my lack of experience with systems has forced me to work around problems as long as I can instead of solving them right away. But hey! This is my first real solo game development project. That’s part of it.
Join Our Community & Future Playtests!
As we dive deeper into production, I hope to hold irregular playtests to gather your invaluable feedback. The best way to stay updated on this and to become part of our growing dwarven clan is by joining our official Discord server.
Join us here: https://discord.gg/prF4CrRSrg
Into The Deep Demo Surfaces – Grab Yer Axes and Plunge In!
Hey everyone! I’m excited to announce that the first demo of Into The Deep is now live and available to download on itch.io, as well as playable directly in your browser.
About the Game
Into The Deep is a turn-based tactical adventure game that plunges you into the dark depths of a lost dwarven city. You’ll lead a brave group of dwarves through dangerous catacombs, fighting to reclaim their home from an ancient evil.
This is my first game, and it began as a learning project in early 2024. Now, I’m finally able share a playable version with all of you! The game still has a long way to go, but I want to gather feedback from players as fast as possible, because I’m completely unable to say if I go the right direction without help. In Germany we have a saying “I can’t see the forest through all the trees”. And that sums it up quite well.






What’s in the Demo?
This demo focuses on giving you a feel for the core gameplay mechanics. It’s centered around tactical turn-based combat, where your squad of dwarves must outsmart enemies in strategic battles. While there’s a lot more planned (like story and progression systems), this demo gives you a glimpse of the core of Into The Deep.
You’ll have access to:
- Two playable levels that showcase the tactical combat system.
- A few initial abilities for the characters Amos and Rocky.
- The chance to experiment with different weapons, skills and strategies
- Three enemy types
What’s missing?
Quite a bit! There’s no story or progression yet, and a few key features—like camp upgrades, more levels, and new characters—are still in development. But your feedback at this stage is incredibly valuable!
What’s Next?
Here’s a preview of what’s coming up:
- Camp Expansion: Upgrade your camp to unlock better gear and recruit new characters.
- New Characters: Amos and Rocky will receive more unique skills, and a third dwarf will soon join the team.
- More Levels: New, more challenging levels are in the works.
- Items, Skills, and Loot: More equipment, abilities, and loot are on the way, including some exciting new headgear and abilities.
Regular Updates
I’m working on the game daily, and I plan to release updates on a regular basis. You can expect to see new features, improvements, and bug fixes rolled out frequently. Keep an eye on this page for the latest news and changelogs!
Join the development journey!
I’m still learning as a developer, and I’d love to hear what you think. Your feedback will directly influence how the game evolves! There’s a feedback form in the demo (though currently not working due to a Trello issue), and you can always join my Discord to chat, share ideas, or report bugs.
Thank you all for your support! I’m looking forward to hearing your thoughts and seeing where this journey takes us.
But most importantly: Have Fun!
– Tobi
Into The Deep: A Tactical Sidescroller Adventure – Announcement
Hey everyone! I’m excited to share that the Into The Deep demo will soon be available on itch.io. You’ll also be able to wishlist it on Steam!
About the Game
Into The Deep is a tactical sidescroller inspired by games like Steamworld Heist and XCOM. This is the first game that I plan to finalize and release, and I’ve poured a lot of time and passion into it. I started it as a learning project, and now I’m eager to see how players will respond. I learned a ton! I would have done many things different if I would start again. But it works! I’m really looking forward to it and to start my gamedev journey with it.






What to Expect from the Demo
In this early demo, the focus is on the core gameplay mechanics and the overall feel of the game. Although the story and progression aren’t included yet, I’m eager to hear your thoughts on the gameplay. You’ll experience turn-based tactical battles, leading a group of dwarves in strategic fights against their fallen brothers and other dangers lurking in the dark.
Join the Development Journey
As a new developer, I greatly value your feedback. I’ve included a feedback form directly in the game, and I would love to hear your thoughts on how to improve the experience. Whether it’s about the gameplay, controls, or overall vibe, every bit of feedback will help shape the future of Into The Deep. Also: I need to know if there is any demand for a game like that.
To stay connected, join my new Discord to chat, share bugs and features ideas, and keep up with the latest development updates. I’m committed to being as transparent as possible, and I’ll regularly share progress on Discord and my Development Trello.
Join the Discord Community | Follow Development on Trello
Subscribe to my newsletter!
C# / Unity Tip: Embedding quotes within a string
We all know how it goes. As soon as we are adding a bit of juice to our strings, it get’s messy. As I was building a modal for my UI System and writing down some placeholder texts, my OCD began to tingle.
string message = $"Do you want to leave this level? \n Loot collected: {coinpercent} % <sprite=\"uiicons\" name=\"coin\">";
I dont know why, but the standard “escape with backslash” approach is somewhat unreadable for me. One method would be to shift the problem and use string interpolation like that example below, but that also makes it a bit more complicated.
string spriteTag = "<sprite=\"uiicons\" name=\"coin\">";
string title = $"Do you want to leave this level? \n Loot collected: {coinpercent} % {spriteTag}";
Precede with @ and use double quotes
A quick google search later (ChatGPT failed) I found another approach, that I was unaware of.
If you precede the string with the “@” character, you can use a double set of quotation marks to indicate a single set of quotation marks within a string. If you prefix the string with the “@” character, you can use a set of double quotation marks to specify a single set of quotation marks within a string. And it makes it more readable. Have a look:
//Standard Method
string message = $"Do you want to leave this level? \n Loot collected: {coinpercent} % <sprite=\"uiicons\" name=\"coin\">";
//String Interpolation
string spriteTag = "<sprite=\"uiicons\" name=\"coin\">";
string title = $"Do you want to leave this level? \n Loot collected: {coinpercent} % {spriteTag}";
//@Method
string message = $@"Do you want to leave this level?
Loot collected: {coinpercent} % <sprite=""uiicons"" name=""coin"">";
One Caveat however: The @ character in C# treats the string as a verbatim string literal, which means it includes all whitespace and line breaks exactly as they are written. This includes the indentation at the start of the line. So if you are in Code and use indentation, it gets shifted.
But nevertheless. Cool to learn some different approaches.
C# / Unity Tip: Get the index from end of an array or list
So, I was in the midst of developing my game when I wanted to retrieve the penultimate (I looked it up, it exists) member of my pathfinding array to determine if the point before the ULTIMATE target is reachable. So, naturally, I used the old self-referencing line to get the work done and created a static method to do the job.
...PathExtensions.GetPositionOnPath(path, path.vectorPath.Count -2)...
/// Method to retrieve the index from the end
public static Vector3 GetPositionOnPath(Path path, int i)
{
return path.vectorPath[i];
}
But wait! Something in the deeper parts of my brain itched. There was some other way to achieve this much more elegantly. And yes, I was right! Again!
INTRODUCING THE ^_____^
After a quick Google search, I found the answer. With C# 8.0 and later, you can indeed use the caret symbol (^) to index arrays, which is known as the “index from end” feature. Nice! It is now much more readable and easier to maintain.
...PathExtensions.GetPositionOnPath(path,^2)...
/// Much simpler method to retrieve the index from the end
public static Vector3 GetPositionOnPath(Path path, Index i)
{
return path.vectorPath[i];
}
Some examples:
string[] colors = { "red", "blue", "green", "yellow", "orange", "purple", "pink", "brown", "black", "white" };
// Accessing the last element of the array:
Debug.Log(colors[^1]);
// Output: "white"
// Accessing the second to last element of the array:
Debug.Log(colors[^2]);
// Output: "black"
// Accessing the third element of the array:
Debug.Log(colors[^3]);
// Output: "brown"
// Accessing the first element of the array:
Debug.Log(colors[^10]);
// Output: "red"
Hope that helps! Bye.
Official documentation:
Building a flexible drag and drop hacking system with Scriptable Objects.
The Mission of this devlog: To provide players with the power to hack various objects in the game world, unleashing a multitude of actions, from disabling cameras to causing explosions. In short: Causing Mayhem. So, let’s get right into it.
Drawing Inspiration from Watch Dogs
Watch Dogs, a game that allows players to hack into an interconnected city, served as my primary muse. I was captivated by the idea of giving players the ability to manipulate their surroundings and devised a plan to bring this level of interactivity into my own project. Also I am very inspired by its clean and functional UI.
Conceptualizing the System
My system revolves around a few core components:
1. HackableSO (Scriptable Object): At the heart of my system lies the HackableSO, a Scriptable Object representing objects in the game world that can be hacked. Each HackableSO carries critical information such as descriptions, sprites, battery costs (if applicable), and most importantly, a list of HackableActionSOs.
2. HackableActionSO (Scriptable Object): These Scriptable Objects hold the logic for actions that can be executed on a HackableSO. Actions like “Disable Camera” or “Trigger Explosion” are defined as HackableActionSOs. They encapsulate the execution logic for their respective actions.
3. Drag-and-Drop Interface: My system makes it possible to include as many interactions to one hackable as I want. Just to select a HackableSO and attach HackableActionSOs to it. Done.
4. Runtime Execution: When a player decides to hack a HackableSO, all the associated HackableActionSOs spring into action, executing their designated functions.
Code Examples
Here’s a sneak peek into the code that brings my dynamic hacking system to life. I’ll focus on the two key Parts: HackableSO
and HackableActionSO
. These just get called via a hacking ability like that: hackableSO.Execute();
// HackableSO.cs
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "Hackable", menuName = "Scriptable Objects/Hackable", order = 0)]
public class HackableSO : ScriptableObject
{
// ... (other variables)
public List<HackableActionSO> hackableActions;
List<HackableActionSO> instances = new List<HackableActionSO>();
public void Initialize(Transform position, GameObject gameObject, ObjectHackable objectHackable)
{
// Initialization logic for HackableSO
// Instantiate HackableActionSOs and add them to the 'instances' list
}
public void Execute(Transform position, GameObject gameObject, ObjectHackable objectHackable)
{
// Execution logic for HackableSO
// Loop through 'instances' and execute associated HackableActionSOs
}
public void Deinitialize(Transform position, GameObject gameObject, ObjectHackable objectHackable)
{
// Deinitialization logic for HackableSO
}
}

In this code snippet, HackableSO
is responsible for initializing and executing HackableActions. It maintains a list of instances of HackableActionSOs
to ensure that each action can be executed independently.
// HackableActionSO.cs
using UnityEngine;
public class HackableActionSO : ScriptableObject
{
public virtual void Initialize(Transform senderTransform, GameObject senderGO, ObjectHackable senderObjectHackable)
{
// Initialization logic for the action
}
public virtual void Execute(Transform senderTransform, GameObject senderGO, ObjectHackable senderObjectHackable)
{
// Execution logic for the action
}
public virtual void Deinitialize(Transform senderTransform, GameObject senderGO, ObjectHackable senderObjectHackable)
{
// Deinitialization logic for the action
}
}
Meanwhile, HackableActionSO
serves as the base class for all hackable actions, providing methods for initialization, execution, and deinitialization, making it easy for me to create custom actions.

Here is an example for that Hackable Action that just instantiates Objects like particle effects and sound.
public class InstantiatePrefabAndSound : HackableActionSO
{
public bool stopAfterSeconds;
public float secondsToStop;
public List<GameObject> ObjectsToInstantiate;
public List<AudioClip> audioClips;
public override void Initialize(Transform sendertransform, GameObject senderGo, ObjectHackable senderobjectHackable)
{
// Additional initialization logic can be added here
}
public override void Execute(Transform sendertransform, GameObject senderGo, ObjectHackable senderobjectHackable)
{
foreach (var gameObject in ObjectsToInstantiate)
{
var go = Instantiate(gameObject, sendertransform.position, Quaternion.identity);
go.transform.parent = sendertransform;
go.SetActive(true);
if (stopAfterSeconds) Destroy(go, secondsToStop);
}
foreach (var audioClip in audioClips)
{
// Play sound once
AudioSource audio = senderGo.AddComponent<AudioSource>();
audio.clip = audioClip;
audio.spatialBlend = 1;
audio.Play();
if (stopAfterSeconds) Destroy(audio, secondsToStop);
}
}
public override void Deinitialize(Transform sendertransform, GameObject senderGo, ObjectHackable senderobjectHackable)
{
// Additional deinitialization logic can be added here
}
}
Devlog: Refactoring Interactive Screens
Since the beginning of my project, I have placed great emphasis on ensuring that the in-game screens are interactive and have a credible interface that fits the scenario. Sometimes with more success, sometimes with less. I had three different ways to interact with in-game desktops:
- Transmitting UI events via Raycast and translating Collider coordinates into Canvas coordinates.
- Translating mouse position to relative cursor graphic position within the Canvas. Raycasting from the cursor graphic to the contents.
- Activating a fullscreen UI upon interaction with the PC.
As I prioritized immersion, it was initially essential to me that when using the interfaces, the environment and the monitor were visible. While it looked cool and somewhat worked, it only worked partially. Sometimes clicks were not registered, double clicks even more often, and dragging elements was a different story altogether. Stacked Canvases? Forget it. They didn’t even exist for my raycasts. My self-hacked option number 2 actually worked the best. So well that it was the standard for most of my project’s development time. The problem was that it was so dependent on the cursor that, depending on the cursor’s position on the Canvas, it could only reach a certain height or width. Since you can’t directly control and set the mouse cursor to zero in Unity, this issue was relatively common. Also. The different Unity Event Systems for UI controls still give me a headache. Draghandler? Doubleclickhandler? Handlerhandler? This was just trial and error all the day.
Stick to the MVP
So, I reflected on what it means to build a prototype. It should work, and the polish comes later. If I really wanted to deliver something robust, I had to rewrite this core component. So, I did just that. After hours of research, along with many people facing the same issues as me, I came across several valuable insights (https://forum.unity.com/threads/handling-pointer-events-on-render-texture.1158272/#post-7432208) and tutorials (https://www.youtube.com/watch?v=fXsdK2umVmM) that helped me a lot, but there always seemed to be some crucial thing that didn’t quite work.
I’ve been waiting for a sale on Dream OS, but somehow, it hasn’t happened. So, I watched the videos by Michsky, the publisher of Dream OS, and there it was, a completely different approach. Apparently, they simply open a Screen Space Canvas, cleverly disguised through a well-directed camera movement. Looked easy enough. So, I opened Unity, placed the computer preset, and started experimenting. Within two hours, I had a completely robust solution up and running.
My simple Solution
- Put a Canvas in Screen Space Camera-Mode and Render a Render Texture
- Put a Canvas in the Game on a Display Object with the same Aspect Ratio
- Inside is a Raw Image which displays the Render Texture and fill the Canvas
- This ensures that it’s the same size and lighting (unlit) as the Full Screen Overlay Canvas
- You can also use a normal Plane and use an Unlit Material with the Render Texture as Base Texture, but I didn’t quite get it right.
- Put a Cinemachine Virtual Camera with a custom Blend in Front of the In-World-Canvas and fit it in
- The Player Interaction with the object does the following things
- Deactivate The Player Controller
- Activate the Cinemachine Virtual Camera to initiate the Blending “animation”
- After a given time (here 1,5 seconds) put the Screen Spaces Camera Mode to Screen Space Overlay
- Check if the player is in visible range to enable or disable the render texture camera canvas to save performance. I just checked with a trigger volume. Works great.
- Done!
The immersion might not be as stunning as with the world space solutions, but the UI here is native, so all functions work flawlessly. I think I’ll keep it for now. Additional benefit: I dont have to implement animations for the character.
To really show off the depressing office flair, I want to go for a 90s Windwos aesthetic. Luckily, there’s a cool asset called 90’s Desktop UI that I can use as a base. Together with the aesthetics of the Chicago95 icon set, I’m sure I’ll conjure up some excellent desktops. I’m looking forward to it.
Limitations: The Blend will only work in a 16:9 aspect ratio. I’m not a Unity UI Expert yet.
Devlog: Litte box of joy
So, I’ve spent the last few days sorting through the mess in my project and rolling back to an earlier state from my trusty git repo. Gotta admit, the motivation’s been taking a hit with all the rewiring and development work looming ahead. But you know what? Today was a different story. Managed to wrap up all those loose ends and finally jumped back into the development phase where the real fun is. Feels awesome to just let loose and work on some simple, quirky mechanics again.
I was just thinking about my Reddit thread asking for ideas about indoor stealth mechanics. Instantly, my brain went, “the Box!” Seriously, the simplest and coolest idea. Spent about an hour or so putting it all together: rough animations, particle effects, an Ability class, and the interaction event that kicks it all off. And guess what? It’s like the perfect little chunk of joy.
Found the fun!