Home Artists Posts Import Register

Content

I wanted to get back to making Kingdom Scrolls because it’s an idea that I really love. The “old” world, titled “Kingdom Scrolls RPG” was sort of left on a cliffhanger as I only wrote one story-line before moving onto other projects. Since then, the old world has remained pretty buggy, and is stuck with limited features since it uses the old SDK. Remaking the world in Udon would allow me to add many features I either couldn’t implement in the old version. Besides, I’ve always said, making a second iteration from scratch tends to get pretty good results.

Step one: Brainstorm a bunch of ideas

Normally, a good first step is to come up with a solid vision for the world as a whole. But since this was a remake/sequel to an existing world, I focused on improvements to the old version. My initial wishlist included:

  • Shorter, more structured campaign quest-lines
  • Better art in the world that corresponded with your stats
  • Jail cell for roleplaying purposes
  • Subordinate roles so you could have multiple people making decisions,like “High priest”
  • Make the game way less likely to break by re-using the same few scroll objects
  • Hats/crowns and other props to supplement avatars/role playing
  • Bigger and more optimized throne room
  • Incorporate the passing of time, for lighting and storytelling purposes
  • Randomized outcomes to certain scrolls for more replayability
  • Ability to customize your game with some sort of fill-in-the-blank system
  • Better music

Also worth mentioning is I like to listen to themed music while brainstorming ideas, writing the code, making the art, etc. There are some pretty good fantasy RPG-themed background music playlists on YouTube, intended for tabletop RPG players I guess, that I listened to pretty much the entire time I developed this world.

Step one: Make sure the idea is technically possible

Before getting started I had a good feeling that what I wanted to do for Kingdom Scrolls v2 would work out fine, but it’s always good to double check before getting too invested in an idea. Sometimes making a prototype is the only way to know for sure, but luckily, the general concept of the game was successful in the past.

One major point to consider was whether I could handle loading scroll data into the world. This would be a very data-driven game, and if I couldn’t figure out how to import massive amounts of character scripts, this would be a show-stopper. Almost all the content for my Catch That Phrase world is just loading data from a spreadsheet so I planned to do the same thing again, except… using a more complicated spreadsheet. So that was probably fine.

The physics interactions are pretty simple too. Granted, working with VRChat pickups can be really annoying, but coming from the most recent Kitchen Cooks world, I knew I could come up with a plan that avoided most of the weird problems with pickups. If a scroll object glitches out as weirdly as the kitchen cooks food objects do sometimes, the Kingdom Scrolls could end up being unplayable. But honestly, anything would be better than how glitchy the old version was.

Step two: Start making the scroll

I figured I would skip making a playable prototype and instead jumped right into making the scroll object. Scrolls are an important game object in this world-- the game hinges on the scrolls working properly and players will be looking at them more than any other object. I am also personally drawn to “UI Design” parts of the game. I think it’s worth spending time on VR interfaces as soon as possible and invest time in making them feel nice to use and pleasant to look at. The scroll model from the old kingdom scrolls was a good place to start, but I wanted to make a few modifications.

  • Made the scrolls thinner. The cylinders at the top and bottom were really large. By shrinking their radius but leaving them the same width and distance apart, the scroll feels less cartoonishly thick and won’t hover above the podiums so much.
  • Colorized character name. From playtesting the first kingdom scrolls game, sometimes it was hard to grab the right character quickly. A subtle hue could help with that, for example all scrolls from the “Squire” character could say “Squire” in purple, while “Blacksmith” is always blue, etc.
  • More readable font for the “blurb”, which is what I call the large chunk of text that the character reads from. This is essentially a script and needs to be compact and readable. The old font was too thin, with too much space between letters, and was more suited for “fancy looking” titles. I wanted a bolder and more “scribbly” font for the main body. If the letters have less space between them, I could fit more text on the page, too.
  • Use Unity’s “Horizontal Layout Group” component for the options listed at the bottom. In the old version, scrolls were either one action (approve) or two actions (approve or deny). But they actually just did the same thing. For this version I wanted to enable special “advisor actions,” which means sometimes you have a third action with a custom footnote like “arrest” or “cast spell”. With a variable number of actions, I did not want to hand-make all the lists of icons. With a Layout group, all I need to do is activate/deactivate the icons I want or don’t want, and Unity automatically arranges the icons horizontally and spaces them apart evenly.

Step three: Make a scroll data importer

“Kingdom Scrolls” involves a relatively large amount of data as far as game worlds go. Each scroll has a script, decisions, and consequences attached to it. And there are a lot of scrolls-- ideally several hundreds of scrolls. Copying and pasting hundreds of scroll objects, and typing the scripts and stats into individual text boxes individually would be crazy. Instead I type all the scroll data into a spreadsheet and load it into the game before uploading the world. If you’re not familiar with spreadsheets, they are a type of digital document specifically for storing lots and lots of data, often numbers. By using a spreadsheet I can edit all the scrolls in one place, then download them all into the world with the click of a button. Visually this looks way more organized than editing individual scrolls, and it saves a ton of time.

In the spreadsheet, each row represents one scroll. In each column I can specify:

  • What story campaign the scroll can appear in. If the scroll can randomly appear in any story (like random citizens of the kingdom with generic concerns), this is left blank
  • Conditions that filter when this scroll can appear. For example, a certain character might show up to sell you weapons, but only if your force is low. If left blank, there is no restriction on when this scroll appears. This was not a feature in the old version of the world, and I need to be careful not to add too many restrictions that raise “low” stats, otherwise the game might go on forever.
  • An identifier “nickname” that I use to refer to this scroll in the code. Basically, some scrolls can spawn other scrolls depending on the player’s decisions. For example, choose “yes” to spawn scroll #1, choose “no” to scroll spawn #5, etc. But I don’t want to refer to scrolls by number, in case I want to rearrange the order of the scrolls in this spreadsheet. Instead, I refer to consequences by “scroll identifier.” Not every scroll needs an identifier, so this can be left blank.
  • The character name, blurb, and prompt text that you read from the scroll. There is no limit on how long these can be, since the text on the scroll will shrink automatically to fit all the text, but I still set the column width in the spreadsheet to visually represent how long a character/prompt should be.
  • The stats that change when you choose “Yes”, “No”, or the special advisor action. There are six columns for each: Gold, People, Morale, Health, Force, and Quest progress. Positive numbers make the stat go up, negative numbers make it go down, and leaving it blank means that stat is unaffected. I set up “conditional formatting” in the google document for these rows so the positive or negative numbers are color-coded, that way at a glance I can see if there are too many “take away gold” or too many “gives morale” for the entire game with just a quick glance through the document. I can also quickly tell if a stat is overused or underused. Overall, I prefer the different stats to be pretty balanced.
  • The scrolls to spawn if you choose “Yes”, “No”, or the special advisor action. These refer to the identifier column mentioned above-- the game will look for a matching scroll identifier and spawn that scroll. I just need to make the identifier names match in this spreadsheet. The old version of kingdom scrolls supported these decision results, but version 2 supports a random chance of a new scroll spawning, if I want. For example, if I want saying “yes” to have a 50-50 chance of spawning scroll A or scroll B, I can do that. It’s also possible to have a 10% chance to spawn scroll A, and leave a 90% chance to spawn nothing at all. For example, when responding to a scroll, maybe there is a small random chance the character will return with something to say on the next turn.
  • The special “advisor action.” In addition to “Approve” and “Deny”, I can specify a special third action. This action can have a special icon and caption at the bottom of the scroll. For example, maybe if a character comes to you with a shady deal, you can “Approve”, “Deny”, or “Arrest” them, if I specify “Arrest” in the “Advisor Action” column.

In order to get the time-saving benefits of using a google spreadsheet, I had to write some code to actually bring the data into Unity. I made my own editor script for this particular job. Editor scripts are great because they let me automate time-consuming or computationally complex tasks, which is perfect because that’s exactly what this is. And best of all, editor scripting is totally separate from the actual world itself. Their only purpose is to add features to the Unity editor itself, which I use to make the world. I can do complex functions, access the internet.. Basically do anything with an editor script, whereas the game code is limited by what Udon can do.

The data-loading script took a while to write, but it’s worth it because of how many scrolls need to be loaded. It might be intimidating to look at, especially if you’re not into coding. The entire script is 229 lines of code long, and I won’t post the entire thing here. Besides, I didn’t really put comments in my code so you can even tell what it does at a glance, which you’re supposed to do when sharing it with other people. But since this program is basically just step-by-step instructions for Unity to follow, here’s a breakdown of what those steps are:

  • Pressing “Menu>Kingdom Scrolls>Import Scroll Library” starts the process
  • Pop up a box that asks if I want to download the spreadsheet from google drive or just use the most recently downloaded data again (which I might need to do sometimes).
  • If you want to download from google, connect to the docs.google.com/spreadsheets/xxxxx URL I specified ahead of time and download the data.
  • Cut up the big chunk of text we downloaded into a nice list of “rows,” just like the spreadsheet.
  • Skip the first row because in the spreadsheet, row 1 is just the column titles, not a scroll.
  • Delete all the “old” ScrollDatas. ScrollDatas are invisible objects in the unity scene and all they do is hold information.
  • Convert each row into ScrollDatas. I have a prefab that’s a “blank” ScrollData. You can use prefabs to spawn one blank ScrollData at a time, then edit it.
  • For the spreadsheet cells that are numbers (like the Yes/No gold, morale, etc) convert the “text” into “integers”.
  • Put all the information, script, etc in the ScrollData. Repeat for all the rows!
  • After all the ScrollDatas are spawned, go back through all the rows and link the related ScrollDatas together (Like saying yes to scroll 5 -> spawn scroll 8). You can tell which ones are linked together based on the “Identifier” name column. I have to do this last because all the ScrollDatas need to exist first.

Step 4: Load data onto scroll pickups

Once loading ScrollData into the Unity scene (the “hard part”) was over with, I was excited to work on one of the easy and fun parts of this game: finishing the actual scroll pickups. The system I settled on would make scrolls as absolutely reliable as possible, unlike the pickups in Kitchen Cooks. Instead of having a ton of scroll pickups like the old kingdom scrolls world, there would be a fixed number of actual scroll pickups. I thought 6 would be a good number to settle on since there should really only be a maximum of 6 characters lined up in the throne room at one time. Then, I would re-use those same 6 scrolls. When a scroll is resolved, it goes invisible instead of destroying itself. For the next round, it reappears, loaded with new data, and respawned at the spawn point. Re-using objects instead of completely destroying them and spawning “new” ones is called “object pooling,” and the 6 scrolls are called the “object pool”. When each round starts, the Master’s computer is in charge of choosing which scrolls to use, and it tells everyone else to load the chosen ScrollData onto each of the 6 scrolls. And if you only need to spawn 4 or 5 scrolls that round, the unused scrolls simply stay “invisible” until they are needed in the future.

The data current shown on the scroll also needs to be synced for late joiners.That way, people who join the world late will see what everybody else sees. Normally you could just store this information on the scroll (For example, which ScrollData to show) and mark it as “synced” in Udon, which means everyone will see the correct value, even if they join late. Normally that’s all you would need to do, but I learned something when making Kitchen Cooks: If you put “synced” data on a pickuppable object, it will change weirdly when you drop the object and somebody else picks it up. This is because VRChat dynamically chooses which player “owns” an object, and therefore has the “final say” about what data value is truly shared among all players. I don’t like that, so I set up a “buddy” object for each Scroll pickup. The only thing these buddy objects do is store a “sync” enabled number representing the most recent ScrollData loaded onto a scroll, so when someone joins the instance late, they see the right text displayed on the scroll. Most importantly, these buddy objects are technically not the same object as the scroll pickup, so the “Master” player will always be in charge of what this value is. The master client is the one choosing which data is loaded after all! Some day, I should really go back and add this buddy-object feature to Kitchen Cooks, unless VRChat comes out with an Udon update that does something better.

Step 5: Make tools that interact with the Scrolls

Next, I added the special effects/models/sounds for touching the scroll with a quill. The logic goes:

  • If a scroll isn’t resolved yet, and a ResolveTool (a quill, stamp, etc) touches it, mark the scroll as “resolved” and remember what decision you’re trying to make
  • Do the sound effects for the type of decision you’re making (approve = scribble sound, etc)
  • Wait 1 second
  • Do the “poof” effect and make the scroll disappear. The audio player chooses between 3 random “poof” sound effects, and chooses a random pitch. I love doing this because it adds just a little bit of variation to sound effects that you hear very often.
  • Finally, adjust the stats corresponding to the decision you made. But that will come later...

Step 6: Make the campaign manager and objectives

This was probably the most rushed and unfinished part of the old kingdom scrolls world, so I wanted to do it better for version 2. Unfortunately, (spoiler alert) when I finished Kingdom Scrolls v2, I only included one story campaign, “Attack of the Orcs,” so you won’t get to see this feature in action until I eventually (hopefully) add another campaign. But basically, this feature just lets you select which scrolls you want to play with.

Each set of scrolls will tell a different story, with unique scrolls related to that story. Furthermore, the story is broken up into several “objectives,” which are like chapters in the story. For example, in “Attack of the Orcs,” the players have to deal with an invading army. The first objective is to “Survive the attack.” That means at the start of the game, you will be shown a variety of scrolls that involve making choices to defend your city walls, launch counter-attacks, etc. In the second part, you have to “Repair your kingdom,” and in the final objective/chapter, you “Negotiate peace with the Orcs.”

If you complete all your objectives without running out of money/morale/force/etc, you win! But how do you complete an objective, and move onto the next one? Why, the multi-purpose “quest” meter, of course. Scrolls can affect your “quest” stat, and when it reaches the maximum value, you complete your current objective and the game switches to the next one.

I define each campaign and objective similar to how I define Scroll Data- there is some UdonBehavior representing each campaign, and each one has a list of text strings representing each objective. This is fine because the only real difference between each campaign and between each objective is the different text that appears in various places, such as the victory message and objectives checklist.

Step 7: Spawn the desired scrolls every round

Each “round” of the game starts with choosing 6 ScrollData scripts, loading them onto the 6 scroll pickups, and respawning them on pedestals. But how do you choose which scrolls to use? It’s slightly more complicated than just choosing a random scroll from my big list of ScrollData.

  • I want half of the scrolls each day to only be scrolls that fit the story the player selected in the campaign manager.
  • I only want story scrolls that make sense for the current objective in the story.
  • I want the other half of the scrolls each day to come from the big pool of non-story-related scrolls.
  • I want the scrolls to show up in a random order each time I play the world.
  • I want as few “repeat” scrolls as possible. Show me new stuff!
  • If I run out of scrolls, then you can start spawning the old scrolls again.

To make this happen, I made two lists, which act like decks of cards.

  • When you start the game or reach an objective, make a new “Story” deck with only the story-specific scrolls for this chapter in the story.
  • Make a separate pile for ALL the random/generic scrolls.
  • Each day, spawn the next three scrolls from the story deck, and the next three from the generic deck.
  • If one of the decks is empty, then you can reshuffle it and start drawing again. You will now get repeat scrolls, but that’s okay.

Step 8: Make decisions affect Stats

The stats are really simple, just six numbers that can go up and down. When you sign off on a scroll, the resolving program looks at the scroll data and increases or decreases these numbers instantly by the corresponding amount. The exact values are hidden from the player to make things a bit more interesting, but in reality they start at 10, and are limited between 0 and 20. If these numbers reach zero, you instantly fail the game, and if they go above 20, they just stay at 20.

The fun part is the colorful meters that move up and down on a slight delay, with the accompanying sound effects. Re-designing these meters was actually not super easy. I wanted to keep the big, shiny hourglass design that I originally envisioned and used in the old kingdom scrolls, but I wanted to use a more optimized, compact, and easier-to-read design. I considered using colored flags that went up and down on a rope of some sort, but these animated flags would not look right with the baked lighting on the wall behind them. I decided to once again embrace the “bottle full of glowing liquid” design. I think in my head, this is slightly inspired by those bottles that count the Hogwarts “house points” in the Harry Potter series-- but instead of little gems or sand or whatever they used, I have this abstract glowing liquid.

I used the most optimized transparent shader I could find for the glass geometry on the outside of each meter, and I wrote a custom unlit shader for the liquid meter that fills up inside. It basically lets me set the color of the “outside”, the color of the “inside”, and the fill height in meters. The main trick is that the shader just straight up discards any pixels higher than the fill height, cutting off the shape at a nice flat level. But there’s another trick, too. Normally, cutting a surface like that would just leave a big “hole”, but I added the illusion of a top “surface” by making the surface of the shape double-sided and coloring the inside with a different, slightly brighter color. Since there is no shading or shadow casting in this liquid shader, the top looks flat and “filled in”.

I think the script that animates the meters changing over time is interesting, too. In reality, all the stats change at the same time, but the animation will deliberately only animate each meter up/down one point value at a time, from left to right, and seamlessly skip any meters that didn’t change.

I got the sound effects from free sources online, and pitched them up or down for a little bit of variation each time they play, which is just a trick I like to do with all my little sound effects. The smoke puff particles are actually opaque low-poly spheres that grow and shrink, which is a common and optimized way to represent smoke in VR games because transparent particles are performance-expensive and 2D particles don’t have any depth.

Step 9: Add Victory and Game Over events

Once the game is “winnable” (or at least “loseable”), I consider it “playable.” That means I can start really getting serious about testing the entire package to make sure it’s enjoyable. Which means I can move onto…

Step 10: Adding all the content for real (The fun part!)

Now that my game prototype works, I can focus on adding all the content. It’s so great to have all my worries out of the way, like adding features, or doubting whether the game is fun, or being unsure whether it will work on a technical level. I have a spreadsheet in google docs already configured and infinitely expandable, so… on to writing scrolls!

This part is actually really time consuming, but once I get in the zone, I can write quite a few in one day. I developed some soft guidelines when writing these, originally intended to make sure the game makes sense, feel relatively fair, and avoid unsavory things that I just didn’t want to include on principle. Sometimes these guidelines were a source of inspiration, but they could also just as easily create some writer’s block.

  • Even though it’s a medieval type fantasy setting, I avoided hardcore descriptions of violence. Death is mentioned pretty often, but the violence borders on cartoonish.
  • I keep the gender of the scroll-reading and leadership characters neutral (Ex. “Your Excellency” instead of King/Queen) to not make anyone feel uncomfortable. You can always adapt whatever gender you want into these characters. Non-playable characters are sometimes mentioned, and those actually are gendered most of the time through the use of titles/names (Example: Duke or Duchess).
  • Frequently revolve around everyday townsfolk, artisans, crafts-people, or military careers. I even made a list of common middle-ages careers to use as a reference (Baker, Blacksmith, Sailor…)
  • Sometimes it’s okay to involve modern-day technology or references, but mainly for humor. For the most part, stick to magical or medieval stuff.
  • Choosing certain actions will sometimes spawn another scroll as a consequence-- this can lead to “chains” of scrolls that go on for as long as I want. This can be an easy way to add more content… just keep the chain of events going in follow-up scrolls.
  • Definitely don’t let the chains of follow-up scrolls get too long (more than 1 or 2 follow-ups is probably bad), and never let the scrolls “loop” back on themselves (you don’t want repeat scrolls).
  • Try to balance the non-story-related scrolls between good and bad. These scrolls pretty much exist to extend the length of the game and provide some slight chaos in your stats as you play the campaign scrolls.
  • Try to only have “unexpected” consequences between 1 and 4 points. It’s okay to have even stronger consequences, like 6 or even 8 points, but these should be clearly explained on the scroll! Otherwise, that would be totally unfair.
  • Be sure to include scrolls that have to do with your population or health. It’s very easy to only write scrolls that have to do with money, morale, or force. I had to go out of my way to come up with ideas that affect these lesser-used stats. Speaking of which...
  • When in doubt, use magic. Magic spells, especially dark magic, can be a great way to affect strange attributes of the kingdom.
  • Morally ambiguous choices are tempting and interesting-- I learned this from play testing. Every leader plays differently, but these make the most interesting scrolls. They are a bit harder to come up with, though.
  • Actually punish saying “no” to scrolls. I’ll admit, I could have done a better job of this. If you don’t have consequences for saying “No” to a scroll, you could almost get through the entire game just dismissing every scroll that shows up. Your stats would barely change, but it’s no fun for anyone if nothing ever gets approved, or at least honestly debated.
  • Try to include actions for the advisors as much as possible. I could have done better with this for the Attack of the Orcs campaign… will have to try harder!
  • Make sure the advisor's actions are totally optional, and that their scripts are independent from each other. You can toggle them on and off, and since not everyone has a full group to play with, you can’t guarantee that a certain advisor is in play.

Writing scrolls simply took a long time, patience, and struggling with writer’s block. Eventually I felt like I had enough to provide a unique playthrough or two before getting repeat scrolls, so that’s where I stopped before publishing the world. However, after playing the Orcs storyline so many times, I still wish I spent longer writing content. Since the system I created lets me import as many scrolls as I want with a single click, I intend to make a big update some day with another story campaign and more generic character scrolls!

Files

Comments

Anonymous

Thank you for your hard work

Draken Stark

This is absolutely amazing to read. Thank you for sharing!