Project Theta #11 Visibility Trees

Why is JoJo’s Bizarre Adventure, a 30-year-old manga series, suddenly picking up so much popularity? My first time hearing it was two years ago, from a Japanese colleague in his 40’s. Merely two years later, the internet is suddenly filled with all the JoJo memes. I puzzle over this as I listen to il vento d’oro for the 50th time – and I haven’t even watched the fifth season yet!

Ahem. As I was saying, I made a lot of progress in the past two weeks. No, really.

Code

I dived back into my 3D tilemap system and tackled the visibility group problem last week. In simpler terms, when player enters house the game hides the outside world. Most 2D RPGs cheat by “teleporting” the player to a different section of the map with black tiles around the room, creating the impression that the player entered a house. This can even be done with 3D RPGs with appropriate fade in/out animations.

I don’t like cheating. I want houses to be the same scale from the outside and the inside. I don’t want player to enter a house just to find out it’s magically a lot bigger inside. In this aspect, the Witcher 3 did a great job, where they had no transitions when entering a building and modeled every single house inside & outside!

How might this be an obstacle? Unless the Witcher 3, the player’s view is mostly at a fixed angle throughout our game, like most RPGs. So we can’t adjust the camera to be at a convenient angle when the player enters a house. Instead, we have to hide the walls when that happens.

There are several ways to go about this, but surprisingly few exist that works with our 3D tilemap.

Raycast

Source: Minion’s Art (https://www.patreon.com/posts/19530112)

This method draws a line from the player’s camera to the player’s sprite, and we can find all the tiles that are in the way. With the list of tiles, we can simply not render them, or set them to translucent.

An even better way is to use a custom shader to automatically fade out tiles within some distance from the line-of-sight from player’s view to the character. I found a very interesting blog describing how this can be done. The GIF above shows the opposite effect, but it is just as easy to play around with the range and alpha value to make it so that tiles in front of the character are faded out.

This method has a major advantage in that we don’t need to do any extra work on the tilemap to make this work (apart from writing the shader). However, a major problem is that it doesn’t look great. Imagine you enter a building and all you see is the building’s facade, with a small circle of visibility around your character. It would look like this:

Source: Pokémon Ruby

Not great.

Visibility Trees

This method annotates every single tile with a tag, and shows/hides based on the player’s current position. For example, if player is on “City”, then all tiles tagged with “City” will be visible. If player now moves into “City/Inn”, then only tiles tagged with “City/Inn” will be visible.

This is a tree structure, exactly like a file system. Great, because all the knowledge I learned on operating systems might come in handy now…

(It did not.)

It turns out this is an opportune time to solve this problem, as in Unity’s latest 2019.3 release, we can now save tree in scripts efficiently with the new SerializeReferenceAttribute. Previously, to save a tree to disk in Unity, we first have to flatten it into an array (causing us to use 2x disk space – not that in this use case it’s anything worrying, but I just don’t like inefficiency).

So I created a ScriptableObject that contained my structure tree with nodes containing tag name and identifier. I then added a structureId field to each GameTile. Theoretically speaking, we now just need to toggle tile visibility around the player every time player walks, based on the structure of the current tile.

But it never is that simple.

In order for the whole thing to work, I need to have an efficient editor for the structure tree and for tagging the tiles. This turned out to be the crux of the problem. Writing custom editors in Unity is a pain.

After 20 hours, jumping through many loops, I adapted Unity’s TreeView editor control and managed to make an editor to edit the structure tree. Inside the ScriptableObject containing the tree, I keep a counter for assigning each node a unique identifier. It is crucial for the tiles to store the identifier, and not the name of the structure, so the reference is not broken when we change name.

The StructureTree editor.

The next part took longer as I tried to mimic Unity’s built-in Object picker. With multiple tiles selected, we can assign a structure tag in bulk with this picker. I couldn’t find a proper way to create this window, so instead I just made a custom EditorWindow. However, it is tricky to relay the selection back to the selected editing objects. Since Unity editor UI uses what’s called immediate mode graphical user interface (IMGUI), it doesn’t play nicely with a event-based approach. The object being edited once I select a structure tag might already have changed.

The GameTileEditor, with the StructurePickerWindow open.

I solved this with yet another identifier system. I assign a unique runtime identifier to every single tile being edited (but not persisted to disk, hence “runtime”), which will stay the same until editor reload. When the GameTileEditor opens the StructurePickerWindow, I pass in the list of runtime identifiers of the selected tiles. Once a structure tag is picked, the window writes the picked structure to a dictionary in GameTileEditor. The editor then consumes the results in the next OnInspectorGUI() update.

It was slightly more complicated as I ran around in circles trying to support multi-object editing, as it is simply impractical to tag tiles one at a time. Unity really doesn’t have great documentation when it comes down to the lesser-used details!

The result, though, is beautiful (code-wise, not art-wise):

Art

Y was occupied, but she still sketched a new character. Not exactly what I had in mind when I gave her the description, but we could always use more character portraits!

Narrative

I want to introduce the Continent, where the game will take place. I have chosen a geocentric flat-earth model, a.k.a. the Continent is flat and the Sun revolves around the Continent.

The Sun revolves around the Continent once every 24 (Earth) hours, which we call one day. In addition, the Continent self-rotates once every 360 days, which we call one year. (Technically the Continent is stationary and the sun is rotating on two axes, but that’s a lot harder to visualize.)

Sun-Continent motion.

The continent exists in space as a disk with a radius of 2,000 km, with 1,000 km of land surrounded by another 1,000 km of ocean. This makes the ocean covering 75% of the entire world, as opposed to 71% on Earth.

These traits make some highly amusing world, especially when it comes to seasons. On Earth, seasons are caused by temperature variations due to the Earth’s tilt angle causing a particular place to be closer to the Sun in the summer and farther away in the winter. On the Continent, the same thing happens because the sun is closer during…wait…

It’s not as simple as it first appears!

Expect a lot of math for the next post as I analyze exactly what the four seasons would look like on the Continent!

Project Theta #10

For the sake of studying how to create compelling narrative and quests, I’ve started playing The Witcher 3. I’ve read dozens articles on it (many of them feature the above image prominently), watched my friends sunk weeks on it, and even read all the reviews for the spinoff Netflix show (without watching the show, of course). I was once a dedicated “cloud player”, but I finally decided to blow the virtual dust off my Steam purchase made many summer-sales ago and had a go at it.

The game has paid a lot of attention to details, which I highly admire. For instance, a side quest that seemed to be a “gather X for NPC” at first turned out to be “NPC is lying, beat him up to find out why”. In turn these details imprint a deeper impression of the game world and events to the player. I have yet started designing quests for the game yet, but playing through this game will definitely impact on my storytelling and quest design down the road.

Code

After exactly three months hiatus, I finally started writing code on the game again. Yay!

RPG Maker MV

The only (custom) battle system that remotely resembles what I want in RPG Maker MV, but which will probably take more effort to write than in Unity. Source: patreon.com/lecodeMV

For the past week I considered the scope of the project and whether it is worth it to spend so much time building the game system, when I can just use RPG Maker MV instead. The latter would make a lot of the things easier, but I would have to make many compromises. I decided to investigate a bit further to see exactly what I would lose…

…and it turns out to be quite a lot! Apparently RPG Maker MV only supports the bare-bone turn-based combat. This means the time-based combat system I came up with must be thrown out of the window. That simply won’t do! I prefer spending more time but do things exactly my way instead.

I suppose I have to stick with my 3D tilemap until the end!

Object Database

I also investigated the best way to store data on abilities, items, and units. Fortunately I had a good starting point on how such a system might work, thanks to my years of experience with Warcraft III’s World Editor. It had this nice UI that made editing abilities, items and units very easy.

Unity does not have such a fancy interface built-in, unfortunately (RPG Maker does, though). Therefore I have to figure out the next best thing. After doing some research, there are several candidates: JSON, YAML, XML, and Unity’s ScriptableObject.

The first three formats are mostly the same, text-based representation of objects. A big advantage of text-based storage is that they are portable – I can easily transfer them out of Unity into, say, Google sheets for collaboration. However, there is no built-in editor for these either.

Also, text-based storage means I can’t refer to each other nicely. Say I got an item A that has ability B. I have to store the reference to ability B somehow, mostly likely its name. If I change the name of ability B to C, I have to change the reference in A as well. This is annoying to maintain.

Unity’s ScriptableObjects on the other hand supports references to other ScriptableObjects, so the referencing part is handled automatically. I can also write a custom editor (extra work) to make editing experience smoother. This is the route I decided to go for. I have a folder called Items that contains ScriptableObjects, each one a distinct Item.

The Instance Problem

I quickly ran into another problem with this route, which I will call the instance problem. Suppose we have a base class called Item, then what should an Iron Dagger be? Should it be an instance of Item, or a subclass?

At first it seems like it should be an instance. If we design the base class Item well (in which its effects are represented by a list of Abilities), then an iron dagger doesn’t require additional functionalities.

However, when we start to consider individual Iron Daggers, which has its own durability, random stats, enhancement level, accessories, then it becomes apparent that Iron Dagger should be a subclass. This becomes more apparent when we consider abilities, which has to keep track of its cooldown and current level.

We can have a million classes, one for each item. This seems like overkill and we are essentially hardcoding a database in code! I really didn’t want to go onto this path.

I ended up using a complementary class, called ItemHolder, to solve this problem. The ItemHolder will keep all data about a specific instance of an item, as well as the base item type. For example, the ItemHolder for an Iron Dagger will keep track of its durability, deviation from its base stats, and etc. Similarly, it can keep track of number of times a consumable item like healing potion can be used.

Similarly, an AbilityHolder can keep track of current cooldown and level of an ability. A unit would then have a bunch of ability and item holders instead of actual items. Problem solved.

Art

Y did a bunch of clothing design for the past month!

Narrative

I completed the portion of the story up to which I want to make a game demo out of, so I’m pausing the novel-writing for now. I might spend some time rewording and reshaping character personalities, but those would come gradually. Right now the story spans over 5,000 words, 6 main characters and 2 (story) days.

I also had a long discussion with Y on specific character personalities. I didn’t want to just borrow the usual character archetypes, but rather create nuanced characters that act in unexpected ways. This proved to be harder to achieve than I thought, even in the short two chapters!

Novel-writing aside, I would continue to write snippets here about the game setting in order to flesh out the world.

Project Theta #9

I took a week off on Thanksgiving break. I thought I could write some narrative on the plane, but ended up sleeping the whole way. Y has been dealing with projects and exams, too. But here’s a cat picture to make up for our lack of progress 🙂

Code

Nope. No code for the last month.

Art

Y has been busy with other projects but she managed to finalize Claudia’s portrait. She also wrote a blog post on comic art, in case you missed it!

I might start working on a world map soon, just for the sake of telling the story better. I might also be able to showcase results in this section soon! Read on for more details.

Narrative

For the past three weeks I wrote a grand total of 319 words. You know you are desperate when you are checking word count every ten minutes. The problem is that the story is at the point where the protagonists are about to leave the starter town, and I have not yet figured out what the larger world look like!

In other words, I need a map to continue telling my story. Not just any map though, I want a realistic piece of land worn by wind and rain. I want naturally formed steep canyons and lush plains and snowy ridges and gushing rivers.

Initially, I searched up erosion algorithms (here’s an interesting article about generating fantasy maps, and here’s a paper on multi-layered terrain erosion), but these turned out to be arduous to adapt to my own use. They aren’t interactive in the sense that I can’t quite author the final landscape to match what I have in mind.

I recently found World Creator, which looks like a mature product for generating and editing landscapes. I’m going through the tutorials to see if it can do exactly as what I want it to do. I’m hoping to create a convincing landscape, then generate a drawn world map out of that (complete with country borders and major settlements). Finally, I can import the result, pixelate it, and make it work with my tilemap system in Unity.

Meanwhile, the story will have a bunch of placeholder for landscape descriptions.

Project Theta #8

After 12 years of secrecy during which not a single employee dared to leak a word, Valve announced a new Half-Life game! If this isn’t patience, I don’t know what is.

The original games in the series, Half-Life and Half-Life 2, were pioneers. Each brought about an explosion of new ideas of how games could be. I hated first-person shooter games until I played Half-Life 2. It was completely different from other forms of storytelling that I didn’t know existed. Its cutscene-free, seamless storytelling technique and its fleshed-out sci-fi setting engrossed me deeply. The Half-Life franchise was the sole reason that made me want to work for Valve.

Then there was silence. It was quiet anticipation at first, but as years passed without any mention from Valve of a new game in the series, the silence became deafening (in the form of memes). Half-Life 3 became the biggest conspiracy theory in the game industry. It was the single title that shall not be uttered – the Game Which Must Not Be Named.

I expect great things from it – possibly the singular title that will usher in a new age of virtual reality gaming.

Coding

Another fortnight of no coding. I’m glad that I kept a coding log which will make getting back to coding much easier. I plan to finish more of the story first, before working on the tilemap again.

Art

Y was pretty busy for the past two weeks, but she still managed to finish some portraits.

Here is Claudia, who undertook sword training together with Felix when they were children. They are now traveling together as adventurers.

And here’s a sketch of the mysterious character I mentioned in the last update.

Yep, it looks just like my own sketch…just…slightly cleaned up!

Felix and Claudia are the second pair of characters I’d like to introduce to the story. With their visual design semi-finalized, I might be able to convince Y to draw some comics revealing their relationship.

Narrative

I managed to squeeze out 800 words, about 2/5 of the bit I wanted to write before getting back to coding. Stating the word count reminds me of the time I used to write essays. In reality, writing essays is probably easier than making up a story…

I realized that I was unwittingly influenced by Dan Brown’s writing style. Namely, I tend to write relatively short sections from various people’s view. This is probably going to be annoying when translated into gameplay, but I really enjoy this form of storytelling. Upon visiting his website, I realized that he wrote a new book, Origin!

For reference purposes, I bought all his books…even though the only one I haven’t read is Origin…

Time to reveal another bit of the Continent!

Promptly after its founder Lepton Antima passed away, the mourning Empire was under siege from Gemia. The Void, without a second wielder, would be as useful as scrap metal in stopping the Gemian elite magic corps – or so the Council of Five thought. They quickly ordered troops to be mobilized toward Antima.

What awaited the Gemian army was death. For inexplicable reasons, the Gemian magic corps could not fire a single spell off, as if the Void was present on the battlefield. The defenseless Gemian army was massacred by the charging Antima forces. With heavy losses, Gemia called off the offensive.

This was the first of many times when the Void Barrier repelled the neighboring country’s invasion attempts.

Excerpt from A Brief History of Antima

Project Theta #7

I started a YouTube channel for piano, and I even bought a microphone for this endeavor. As a result, I didn’t write a single line of code for the game in the past two weeks. Instead of feeling bad about it, I felt refreshed taking a break working on the tilemap code.

I did, however, make considerable progress on the story. I fleshed out two more plot-heavy characters and I planned the details of the next couple of chapters. Basically about how our carefree protagonists got knee-deep into the whole mess between the two countries at war. More on that in the narrative section!

Art

I got a couple of semi-finalized character portraits to share! Y has been pondering on the character designs for ages. We had countless back-and-forth discussions on how the male characters should look like, and I think we finally reached agreement.

So, without further ado, here’s Edge (20), the protagonist of the story.

And here’s Felix Mendel (26), who used to be a child prodigy sword-wielder.

Narrative

I really want to focus on the story for a bit, because ever since finishing writing the first chapter of the story back in March, I barely made any progress on it. I keep telling myself that I got the whole story arc plotted out, but there is no content to it! It’s like writing an interface without any implementations and calling it a job finished!

A major blocker for writing narrative happens when the protagonist encounters new characters. How should they act? Why do they do what they do? What are their objectives? What are they thinking? Do they have another side beneath their facade? The questions are endless, and they are all important details to consider. The story cannot progress with empty actors.

So I took some time and brainstormed two more characters central to the rest of the story. A suave guy who just hit 60, and his carefree, mysterious daughter who’s in her mid-20s. I probably can’t reveal more than that without accidentally let out spoilers, but Y might have portraits on them in the next update!

Fun little story. I had a very clear mental image of how the old guy should look like. In an effort to convey that exact image to Y, I promised her I would draw a sketch. I then proceeded to grab my pencil and notebook.

I then Googled “how to draw anime character” and landed on a WikiHow article of the same name. Gotta love WikiHow, they got a guide for everything. After an intense and extensive drawing session, I got this:

I then remembered why I have an artist and closed my notebook…