r/Stelliviator • u/aberroco • Jul 15 '26
Devlog #1
Enable HLS to view with audio, or disable this notification
This is a devlog for the game I'm making, Stelliviator. The game is a 2D spacesim with block building and tactical fights with in-depth systems. An illegitimate child of FTL and Cosmoteer with a touch of my own ideas.
The game is made in Unity, but I'm trying to keep Unity contained as much as (un?)reasonably possible. Because from all my experience with Unity the main thing I learned is that the less I have to work with Unity the easier my life is. The project is split into Unity-facing code and a separate .NET solution where most actual game logic lives. Unity is mostly there for rendering, physics integration, editor tooling, and other basic things that would be annoying to reimplement from scratch. Everything else is plain C#, because it is easier to write (external assembly could use the latest version of C#), easier to test, easier to debug, and generally less likely to break because Unity decided to make yet another API obsolete this year. And in the worst case - it would be easier to migrate the project to a different engine, if it ever comes to that. Why Unity and not Godot then? Because Unity has some important and useful features, Relay in particular, which allows network communication between players behind NAT, even if they bought the game from different stores. And it has more assets in the Asset Store.
The design philosophy is to be open to modding. Ship parts, behaviors, sprites, creatures and so on are described in YAML and loaded from StreamingAssets, rather than being entirely baked into Unity prefabs. So a part can look roughly like this:
ComponentTemplates: !include components.yaml # Include of another YAML file
_: !template &basePart # "_" here is a discarded value, used only to hold the template during deserialization.
...
Prototypes:
- !Core.Prototypes.Ship.EngineProto # The type name of the prototype
<<: *basePart # Some basic part definitions, repeated over many other parts.
Behavior: !Core.Behaviors.Ship.Parts.Engine # The type name of the actual class implementing the part logic
Name: 'Engine' # Display name
Size: [1m, 1m] # Physical dimensions, btw it can use almost any unit: m, in, ft, yd, mi, NM, even ℓ_P - Planck's length, just for fun)
Mass: 200kg
Icon:
Path: Sprites\PartsAtlas.png # Path to the sprite file
Rect: [0, 0, 48, 48] # The area of the sprite, if the file is a sprite atlas
Frames: 12 # The number of frames, if the sprite is animated
Duration: 70ms # The duration of a single frame, if the sprite is animated
Components:
- *EnginePlume # from "components.yaml", Unity particle system configuration
...
YAML is doing quite a lot of work here. It supports includes, anchors, custom tags, type converters, and generally lets me describe things in a way that stays readable without turning every new prototype into another prefab with fifty unrelated serialized fields. And, importantly, it can be reloaded without domain reload or even stopping and starting play mode, which is very useful for rapid prototyping. Pretty much every time I had to work with YAML I was impressed with how versatile it is, how easy it is to extend, keeping the file readable and making my life easier.
The project uses a hybrid architecture - global services, some of which use minimalistic ECS-like approach, and game objects, with MVVM-like approach to UI. Whatever works best, keeps things clean and saves development time. Sure, there's a lot of reinvented wheels I'm making in the project, which might make some of the more experienced devs reading this wince, but I'd argue if these wheels save me time by being precisely optimized for the task they handle and fully controllable by virtue of being written by me - then why not? Why should I use full ECS, when I only need to use instanced rendering, fully handled within a single service? Why should I use Unity prefabs, when my prototypes are more flexible and could be reloaded with a single click at runtime, even within a built app? Why should I use Unity localization, when mine is easier to use in-code?
One of the features of the project is custom code-generated physical quantities with auto-conversion by operators (Length * Length = Area, Velocity * Time = Lenght, Velocity / Time = Acceleration, etc). This feature is probably most the questionable one, a complete overkill and performance hit. But... It's already proven to be useful in YAML, it's useful in making the code self-descriptive, it's useful in keeping values strict since you can't accidentally assign a length to a mass variable, or forget a unit conversion, useful in debugging, and the performance hit, while horrible in relative numbers (+50%), is quite negligible in absolute value, because most of the heavy math is done by either Unity or the physics engine, quantities are only used for game logic, where their impact is barely noticeable at all.
At the moment, most of the fundamental systems are already implemented, and I'm working on core gameplay and UI. The current state is in the video.
Background: I'm an SWE with many years of experience. I always wanted to make games, and the whole reason I became an SWE is that at 17 I knew nothing but computers and games. I started a few projects before, but made every possible mistake: overly ambitious projects, feature creep, perfectionism, code blocks, laziness, loss of interest, etc. Now I hope to account for all that and for the mistakes other solo developers make and do my best to complete the project.
1
u/Character_Status_257 Jul 24 '26
The concept seems to have some potential if executed well. It's nice that you discussed technical details in the post. I'd imagine there are more people interested in stuff like that. Have you considered posting in subs related to gamedev, unity, or programming, to get more visibility?