Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

Advanced search

1402811 Posts in 68129 Topics- by 61757 Members - Latest Member: ranum

October 01, 2022, 07:35:23 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsAutopanic
Pages: [1]
Author Topic: Autopanic  (Read 800 times)
Level 0

View Profile
« on: August 24, 2022, 01:45:56 AM »

I'm currently making a fully diegetic minimalist twin-stick shooter with Rogue-like elements.


An AI assistant wake you up from a long slumber. All you can do is to follow its guidance and ascend to the top floor.


I find 13 Sentinels: Aegis Rim combat visual to be simple and effective, but the combat design itself leaves a lot to be desired. So I wanted to make a twin-stick shooter with 13 Sentinels: Aegis Rim's visual. That's it!

The game eventually evolves into a game with Rogue-like elements because I wanted to make the game about overcoming impossible odds.


I'm doing the devlog retrospectively because I started with zero game development knowledge and stumbled a lot during my development. Only now when the game is nearly finished, I can finally sort my development out and write a cohesive story documenting it.

Visual Design

Since I started this project with zero knowledge about 3D and art in general, I limited myself early on to use only vector graphics and 3D primitives throughout the game.

This decision also has impact on my design. Sometimes I give up on a design only because of my visual design toolset couldn't do it justice. In the end this design choice helped my game to be focused.

Fully Diegetic

For no apparent reason, I've decided to make every single element in my game to be diegetic, as in, existing in the game world. To simply put, for whatever stuff player is looking at, that thing actually has a meaning in-game.
Some quick examples:
  • Instead of just a button prompt, the prompt is your buddy AI speaking to you.
  • Instead of characters speaking to each other without voice acting, they are communicating through text.
This design choice caused quite some issue later on, but overall I think it should result in an interesting experience.

Unity 3D

I'm using Unity3D for the development. I try to avoid 3rd party plugins with the exception of DOTween for easy tweening operation and Shapes for vector graphics rendering.
« Last Edit: September 07, 2022, 02:53:44 PM by dklassic » Logged

Level 0

View Profile
« Reply #1 on: August 25, 2022, 02:53:04 AM »


April 2020, inspired by A Short Hike, I decided to start learning how to making my own game. I started with Sebastian Lague's Twinstick Shooter Tutorial and quickly build up something almost enjoyable:

I also accidentally let the projectiles knockback my shooter enemy, resulting in some cool Shoot & Retreat moment.
I think to myself, wow, seven days and it is already fun. No doubt I can make a game!

So I initially planned the game as a shoot 'em up, and the plan is to finish the game in May 2020.
Looking back, that was definitely possible, just not for me back in 2020.
« Last Edit: August 25, 2022, 04:18:03 AM by dklassic » Logged

Level 0

View Profile
« Reply #2 on: September 05, 2022, 08:39:28 PM »

Early Design

The first iteration of the game is naturally a Shoot 'em Up. Fighting hordes of enemies in a cityscape.

The game is supposed to be about recurring challenge, with some bosses as checkpoints that grant you permanent upgrades.
This is also when the "Fully Diegetic" idea started to kick off. I want players to have a companion commenting on their every defeat (which I didn't know Hades do this back then), and by defeat, being actually dead.
And since after death players have to restart the whole run, naturally they need to recollect their gear from their corpse.
A bit souls-like vibe maybe?

There's also an idea about strategically placing your corpse as a back up for more shield/health to recover during fight.

Scope Change

Because of course there's a scope creep for every beginner's project.
I thought to myself that a game about clearing hordes is not going to sell in 2020, which is later proven wrong by recent success of Vampire survivor. (Had some fun revisiting this idea, but that's for later)
And my initial design revolves around player having an ability to run faster than enemies, which of course makes player completely invincible. So I thought to myself that I need a smaller level. For god knows what reason it never occurs to me that I can add a stamina system which surely works well in Jakob Wahlberg's project GoMechaBall.

Twinstick shooter in small rooms. Time to build a Rogue-like dungeon crawler of sorts.

Level 0

View Profile
« Reply #3 on: September 07, 2022, 09:02:12 AM »

Early Level Design with Wave Function Collapse

I was quite obsessed with Oskar Stålberg's games back in August 2020. Bad North and Townscaper both proven to be some decent piece and showcase the randomly generated with authored visual potential of Wave Function Collapse quite well.

So I tried my hand at writing one such algorithm over several attempts with some success.
Then I proceed to scrap the idea of using WFC.

The reason being although I'm starting to generate some unique geometry (as in not seem like tiles), they never hit any sense of meaningfulness in visual. Oskar Stålberg also implied that Bad North has 200+ pieces of models to be synthesized. As a total amateur in game development in every sense, there's no way I can match that.

The actual level design (or the lack of) will come in much later in development.

Here are some of the WFC efforts:

« Last Edit: September 08, 2022, 10:28:06 AM by dklassic » Logged

Level 0

View Profile
« Reply #4 on: September 09, 2022, 02:56:01 AM »

Early Visual Design

I wanted to do something that is dirt cheap and effective, though I don't really know where I'm going. But I quickly established the style with heavy depth of field and the use of dynamic lighting.

Then I tried an ambient occlusion heavy visual that focuses on color palette swapping. Which almost stayed till the end.

But then the level geometry increased around this time, so I tried my hand at decorating the levels with Unity Particle System. Which I still think looks pretty rad.

However as I slowing move towards a much simple visual choice with most of the visual stuff done with primitives using Shapes, I began to tone down the visual density again.

Since I'm not hitting any jackpot, I decided to work on something else before revisiting visual design.
« Last Edit: September 18, 2022, 01:56:08 AM by dklassic » Logged

Level 0

View Profile
« Reply #5 on: September 10, 2022, 09:48:10 AM »

Minor Burn Out

It is January 2021, my three-month project has stretched into 8 months and I'm not anywhere near the finish line. Actually, I'm not getting anywhere.
But I'm much wiser now, armed with some actual proper game development knowledge and starting to get a grip of what Unity can do properly.

By what Unity can do, I mean it can't do anything. So no more hacking with existing solutions, I must get my hands dirty and start building reliable stuffs. Everything by myself from ground up, so I can know its limitation and know how to expand and fix it.

I decided to build some proper backbone for the project to go forward then grant myself some much needed rest. So I started building:
  • Enemy AI
  • Level Management Tool
  • UI Framework

I'll have to start talking from UI though.

Custom UI Framework

Back then I'm all sold on the new Unity Input System, which has some really promising features and I don't want to walk back to use the old input system. However the new Input System for whatever reason doesn't gel well with their UI Events.

So I need a custom UI framework.

Inspired by Phi Dinh's Recompile, I figure a fully text-based UI would be great for my project.
Although I'm incapable to do fancy ASCII animation and having to support Chinese characters by default ('cause, I speak Mandarin) removes quite a lot of  presentation choices, limiting myself can help me focus more on actual useful stuffs.

Building a robust UI framework is imminent anyways because before that I was debugging by clicking on Unity's editor window. The back and forth between game screen and editor takes me out of the flow, traversing the scene hierarchy doesn't help either.

I started by building an enemy spawner:
An elegant weapon for a more civilized age.

This makes the enemy testing process much easier. No more drag & drop and clicking through scene hierarchy.

The UI framework gradually grows into a behemoth supporting all sorts of stuffs easily. For example, my system menu UI can be initiated with a class that inherits the GeneralUISystemWithNavigation class. Then I can simply do:
    protected override void InitializeUI()
        systemWindow ??= NewWindow("ui_system", DefaultSetup);
        AddButton("ui_system_Resume", systemWindow);
        AddButton("ui_system_Visual", systemWindow);
        AddButton("ui_system_Audio", systemWindow);
        AddButton("ui_system_Control", systemWindow);
        AddButton("ui_system_Accessibility", systemWindow);
        exitUI = AddButton("ui_system_Exit", systemWindow);

And then vuala:

I can also easily define the button's function as such:
    protected override bool ButtonAction() => currentSelection[1] switch
        0 => CloseMenu(true, false),
        1 => OpenSubMenu(0),
        2 => OpenSubMenu(1),
        3 => OpenSubMenu(2),
        4 => OpenSubMenu(3),
        5 when exitUI.Available && !endgame => OpenSubMenu(4), // spoiler?
        5 when exitUI.Available && endgame => OpenSubMenu(5),
        6 => OpenSubMenu(4),
        _ => false

Though all the game's UI are done with this framework, my debug menus made the most out of this framework:

Building this set of UI framework really helps a lot further into development. Though I have to live with the consequence of difficult to do mouse detection later on.

Mouse Detection Difficulty Update - September 11th
Well, turns out I've been scaring myself all these time.
Since my UI system is brute-forced with Unity's Text Mesh Pro, I thought I need some shenanigans or drastic rework to make mouse detection possible.
Turns out TMP can simply retrieve the anchor of each character. So I just record the anchor and check if the mouse's screen space position is within that range, and then it is done.

Probably a bit costly when initializing a large menu (like my debug menu) and not as intuitive as typical raycast approach, but it seems to work just fine.
« Last Edit: September 11, 2022, 10:09:18 AM by dklassic » Logged

Level 0

View Profile
« Reply #6 on: September 18, 2022, 12:40:12 AM »

AI Behavior Revamp

My old solution relies on Unity's NavMesh and NavMeshAgent. This becomes a chore to me later on because:
  • As my levels becomes more dynamic, managing NavMesh becomes a tedious work
  • NavMeshAgent can reliably move towards the destination, but also costs too much to request frequently
  • My gameplay is very fast-paced, so I'd like my enemies to react to player action as fast as possible
So I decided to move to a custom solution that is basically about picking a preferred direction and move forward.

Movement Determination

Generally a level may look something like this:

For each calculation, the agent will check the following things:
  • Obstacle around the agent (e.g. other agents, traps, and decors)
  • Distance and direction towards a preferred location (e.g. movement destination and target agent)
So it's all about avoid bumping into obstacles and wanting to have a certain distance between certain target. Which looked like this:

Then I added some physical constraints to make the agent move more naturally, such as:
  • Having acceleration/deceleration speed
  • Having max speed
  • Will decelerate if the preferred direction is too different from current direction
  • Have a max rotation speed
I could've gone further and have rotation acceleration/deceleration, but I find it somewhat hard to balance around the numbers, so I've decided to omit it for now.
So far so good:

This approach also helps me make some actions more dynamic, such as "Strategic Dash" and "Emergency Evade", for these action can now be used with understandings of the environment instead of a fixed direction and stuffs.
I've then spend some time optimizing raycast with multithread but nothing fancy.

Attack Pattern

I decided to move towards the idea of an attack pattern. To ensure the combat won't become raw skill-based chaos, but a more manageable situation to be learned and resolved by the players.

So I constructed a hefty list of actions available, just to name a few:

And now instead of making multitude of enemy prefabs, I now have one enemy prefab that will instantiate with a EnemySetting scriptable object, which makes modification a lot easier.

Now with enemy behavior revamped, time to add in procedural animation.

Level 0

View Profile
« Reply #7 on: September 24, 2022, 10:21:28 AM »

Procedural Animation

Procedural Animation in my game is a big topic, because basically every single changing element was procedural, i.e. code driven.
I know early on that I'm not going to be doing keyframes at all. Not only because I'm just but one guy, also that I've watched the famous talk from David Rosen about procedural animation in Overgrowth and was convinced that procedural animation can be used to achieve suitably high quality animation with way less effort.

UI Animation

Not much to talk about here due to my simple UI setup, but I do have several glitch effect setup for the windows, which is driven by something like this:
switch (CurrentTransition)
    case WindowTransition.Noise:
        maskIndex[i, j] = UnityEngine.Random.Range(0, TextUtility.FadeIn.Length - 1);
    case WindowTransition.Glitch:
        if (UnityEngine.Random.value > 0.5f)
            maskIndex[i, j] += Mathf.FloorToInt(Time.unscaledDeltaTime / maskAnimationStep);
    case WindowTransition.DamageGlitch:
        if (UnityEngine.Random.value > 0.5f)
            maskIndex[i, j] += Mathf.FloorToInt(Time.unscaledDeltaTime / maskAnimationStep);
    case WindowTransition.Random:
        if (UnityEngine.Random.value > 0.25f)
            maskIndex[i, j] += Mathf.FloorToInt(UnityEngine.Random.Range(1, TextUtility.FadeIn.Length - 1) * Time.unscaledDeltaTime / maskAnimationStep);
        maskIndex[i, j] += Mathf.FloorToInt(Time.unscaledDeltaTime / maskAnimationStep);

Generic Procedural Animation

This part is a bit more fun. Mostly done with DOTween because DOTween is just great. Some examples:
Hit Reaction:
icon.DOPunchRotation(damageForce / enemySize, 0.5f, 10, 0)
Weapon Recoil:
recoilTarget.DOPunchPosition(recoilForce / enemySize, recoilDuration, 1)

Simple, quick to make, and can include the consideration of physicality quite easily.

Procedural Movement Animation

Now comes the fun part, though maybe not much to be explained.
I find that making procedural movement animation is basically programming the process of how the real world counterpart would move:
  • If leg is too far away, move
  • If moving, lean
  • Move faster if displacement is large
Which is as rudimentary as it can be, but this also makes it hard to find resources to follow. I ended up learning more about procedural animation by looking at Jakob Wahlberg's tweets.

Since I revamped enemy behavior, my AI now have some proper physicality in its movement. So as long as my procedural movement animation can automatically accommodate the displacement of the unit, the result will always be great:

And by extension, it also works on player controlled character:

So with procedural animation in place, my game finally looks a lot more complete.

Pages: [1]
Jump to:  

Theme orange-lt created by panic