Now I’m re-starting that project here on Levelcapped.com with it’s own dedicated page for all of my development journals, progress reports, and general information on what it’s like for someone with no game development experience to make a go of creating his own game.
Following not-so-hot on the heels of my not-so-hot request for UI design feedback (thanks to none of you who responded!), I wanted to post what I’ve gotten so far and talk a little about the standards that I’m going to try to apply to the UI work going forward.
As stated in the previous post, there’s not so much a “right way” to handle the organization of code and objects, but there are most certainly “wrong ways”. The quickest way to identify when you’ve turned down the wrong alley is to try and get your UI elements to work together, to access each other’s information, and to take actions that the UI is meant to enact. That’s why the hierarchy of UI elements is important.
This fine diagram to my left is what I came up with for my main menu hierarchy. I need to preface this by talking a bit about the data controller though. The data controller is an empty game object — which means you can’t see it in the game — that has one component: Database. Database is a C# script that handles tracking the state data (stuff that changes when you play, like your character and your progress) and main data (stuff that is always the same, like item stats). The empty game object that holds it is set to not be recycled when we switch scenes, so it will persist throughout the game. In addition, the code is set as a singleton, which means it is self-policing so that it ensures that there’s only ever one copy of the data. The data controller isn’t represented in this screencap, but know that it sits above and outside of the Main Menu Controller.
The Main Menu Controller is another empty game object. It is an umbrella beneath which we will find all of the UI elements that make up the main menu, the loading and saving screen, options, and confirmation dialogs like overwrite confirm and quit confirm. The benefit of this is that the empty game object can hold scripts that we can refer to from anywhere in the hierarchy, but more importantly, it allows us to make a prefab of the menu. A prefab is a “master copy” of an object that we can deploy anywhere in the project. When we make a change to the master object, it cascades to all deployed instances. If we make a change to deployed instance, we can either let that change stand just for that instance or have the instance update the master object. I’ve already created a prefab of the main menu hierarchy, which is why the text is in blue.
So what about the organization itself? There are five main levels: MainMenu, GameList, Options, QuitConfirm, and ConfirmOverwrite (yes, OCD folks, I will change the Quit and Overwrite to match naming patterns).
Main Menu is what you’d expect: the main menu. This is what you’d get when you start the game, or when you hit the ESC key while playing the game. It allows you to start a new game, load an existing game, set options, or quit.
This is where the difficulty comes in. Both NEW and LOAD share the same concept: choose a slot from three options. If it’s filled with details, we need to know what option we chose from the main menu: are we starting a new game? If so, we need to make sure the user knows she is going to overwrite an existing file. Are we loading an existing game? Then we need to get the save game data into Database from disk.
And here’s our load/new UI. The first slot is filled in with an existing game. We simply call it “Save game 1” and display the last save date. The other two slots are empty. If the user is starting a new game, she can choose the last two slots and just start the game. If she chooses “Save game 1” then we need to warn her.
If she chooses YES, then we’ll set up a new game and overwrite the slot that’s currently occupied.
What handles all of this? There are two scripts: Main Menu and Game List.
Main menu is attached to the MainMenuController game object because this handles the opening and closing of panels other than the main menu itself. One thing that UI systems need is a way to handle which windows are open and which are not. One way to do this in Unity is through GameObject.SetActive([boolean]). When boolean is false, the window is inactive. Unfortunately, when a game object is inactive, it is unaddressable, meaning we can’t tell it to show itself because it’s just not listening. To get around this, we put a script at a higher level than the object, create a property, and drag that object into the property. Now, when we want to show the windows, we do so from above the window itself…at the controller level. Currently, the main menu itself isn’t represented, which will get fixed later.
What we do not see are methods called event handlers. These are code bits which the buttons use. When someone clicks NEW GAME, the event handler “hears” the activity and takes an action. We point the button’s click event to that method in order to join the two. Here, we have three event handlers: One to display the game list panel, one to display the options panel, and one to display the quit confirmation panel.
The real tricky part was the game list panel.
In this case, we have the script attached to the UI element itself. Why not attach this to the Main Menu Controller? Well, for one reason: we need to take an action when the UI is activated — when the button on the main menu is clicked. If we put this on the Main Menu Controller then as soon as that object is created (at scene load) then those actions would fire. Since the game list panel isn’t active at that point, running that code is pointless.
The activation action runs the code within Database that loads the list of saved games. We use this to update the text of each button on the panel. If there’s a save game in slot one, then we need to change the text of slot one from EMPTY SLOT to the name and last saved date. We need to have references to these buttons inside the script in order to do this, so we create properties to hold those references. We could technically use hierarchy and search methods to find SaveGame1,2,3 buttons, but searching like that is expensive and doesn’t make the assignment visible through the inspector during design time. We also have a reference for Confirm Overwrite Panel because its visibility is controlled based on the state of the button the user presses, and the action she intends to enact (new or load).
If the user is starting a new game, then Database handles the initialization by loading the master data, creating a new Game State Object, merging data where necessary, and then making all of that available through the Database instance. If the user is loading a game, we load the master data and read the appropriate state file from disk. In the case of a new game, we will then send the user to another scene where she can make some limited customization of her character (since the character has no visible presence, it’s mostly just custom name, gender, and paper doll selection). Then, she’d have to decide whether or not to tackle the tutorial. If she’s loading a game, then we would send her to the scene where she left off when the game was saved.
So that’s it! 1300 words to describe a menu system (be thankful I didn’t include all the code!). Needless to say even something as “simple” as a menu can be more complicated than you know, so remember that the next time you’re ripping into a game about animations or physics — there’s a lot of moving parts, and what you see is only the end result of mountains of effort whose structures are really only as good as the organization of its parts.
One of the cornerstones of the development world is the idea of “best practice”. Since coding is as much about style and flexibility as it is about solving concrete problems and modeling desired outcomes there’s really no one single way to approach a solution…nor should there be! What we have instead is a kind of trend towards certain efficiencies such as least amount of code to get the job done, making it reusable, making sure it doesn’t trip up or over other code, etc. Best practice can be abused when people insist that their way is the only way because anything less is just going to cause your app to sputter and die a wheezing death. But best practices are really the distillation of a whole lot of people’s trial and error, hopefully with a dash of advice from those who created the language.
Finding the “best practice” is often difficult for a few reasons, first and foremost being that as a rule, there is no best practice. Everyone swears by what works best for them. Some people like cars, some like motorcycles, but both will get you to where you need to be so who really cares? The second is that often times developers can be real cagey with their knowledge. There’s some undercurrent that believes divulging experience in development is like a magician telling people how the trick is done, not because it ruins the illusion, but because it suddenly makes the original magician a lot less valuable if everyone can do the same trick.
That’s why I’m throwing this out there in the hopes that someone can at least share some insight into their own experience since it seems like more of what we call a pattern than a practice. A pattern is more of a mindset than an actual flow. It’s how things are arranged so you can get yourself into a practice. In this case, I’m looking for advice on structuring and controlling a user interface in Unity.
And before I get to the question at hand, just a bit of a preamble. The way I’ve been working with Unity UI, I see two methods of wiring up the interaction. The first is to have the UI itself handle interaction with the code that puts and pulls data to and from the game’s data store. The second is to centralize the code that interfaces with the data store, and then have another script on the UI that deals with the UI itself. Then, these scripts communicate among themselves to pass data along.
Option 1: Direct Script Interface
The first option is probably the most direct and easiest to conceptualize. The Unity UI system allows us to draw a box, say, which contains fields for text input (in our example). In order to get this data into the game data store so we can apply it elsewhere, we need to recognize that the textboxes exist.
After we draw our UI, we attach a script to it. This script has properties that are intended to hold references to the UI elements like the textbox (and the button used to submit the data to the data store). When the script receives the command to read the data from the form, it refers to those properties so it can read the contents. It would then take the data from the textboxes and “do something” with it — send it to another part of the game, or put it into the database or something.
The benefit to this is that the UI is completely sorta self-contained. We could copy this and paste it elsewhere and it should work exactly the same, which is one of Unity’s greatest strengths. It’s also easier to manage because we just need to go to the source — the UI elements — and we have access to the visuals and the code.
The downside to this is that we end up with a whole lot of repeated code. Anytime we want similar but slightly different behavior we would need to modify the underlying code and then add a reference to other UI. It also means that we can’t easily take advantage of global patterns such as singletons which allow for persistence of data without having to go “back to the well” of a back-end system. Finally, if we had one script to handle several UI elements, we’d have a whole lot of properties tied to UI elements to deal with, which might make management a nightmare.
Option 2: MVC-esque Interface
This option is more complex, so please bear with me as I try and explain the diagram.
First, MVC is a pattern called “model-view-controller” which puts the display in a “view”, the logic in a “controller” and uses a “model” to represent the data passed between the two. Here, the UI has a controller. This is a game object which centralizes a whole lot of behavior for the express purpose of bundling it together for easy access. Here, a UI controller would be the base of either this or all scene UI elements. We’d have scripts for managing windows in the scene, but also for handling the UI elements (textboxes, buttons, etc).
The difference here is that this script would need to communicate with another script on a more global scene controller. The scene controller is like the MCP from the original TRON: it’s got access to everything you might need, just hanging out in space, easily accessed from whatever and where ever you need it.
The benefit of this method is that the scene controller is all seeing and all knowing. It works for the UI, but it’s also available for other elements of the game. In addition, it can implement the singleton pattern which when combined with telling Unity not to destroy the object on scene transition, offers us a persistent data conduit.
The downside? It’s messy. And complex. Technically, this diagram can be warped a bit. The UI doesn’t need its own controller, for example, and the interface script can live on the top-level element (“canvas”) of each UI we need to communicate with the scene controller. We could also eschew the scene controller itself and make the UI controller the top level way of data store interaction, although we’d lose our data persistence unless we did have some singleton somewhere that wasn’t destroyed when we move between scenes.
So there we have my conundrum. As a hobbyist developer in this realm, I’m not sure what the best option is. I had been using the more complex method previously, but now that I see things in writing I’m thinking of trying the less complex method, although I’m not sure what pitfalls are unaccounted for along that trail.
Are there other methods? This is where I’d love to hear from other developers who have worked with Unity UI and who are willing to offer advice!
This project I’m working on, this cyberpunk corporate financial warfare thing, is pretty simple on the surface. I don’t mean in terms of gameplay; I’m not sure it’ll even qualify as a “game”, per se. Rather, I mean in how it looks when you experience it.
One big disconnect between the consumer and the producer is that the consumer has no idea what actually goes into producing a product. The best that the consumer can do is make logical assumptions, filling in the gaps with knowledge explained or researched, and just glossing over what remains or what’s deemed “unimportant”. One element that I think doesn’t get anywhere near enough interest is user interface design and execution. It’s so critical to the overall operation of the game, but the most attention is receives is when people bitch about how ugly it is or how much room it takes up.
This cyberpunk project is mostly UI. I mean, there’s no little CEO running from map to map collecting resources and turning them into products or anything. You click buttons and slide sliders and maybe enter numbers, and then review your financial empire while you wait for your research or production or distribution or marketing to complete. In order to be as efficient as possible, you’ll need to jump from UI element to UI element, from a broad overview to a micromanagement perspective and back again to make sure you’re not spending money on idle facilities. All of this means I’ve had to really come to grips with one element that I’ve never been really good at: user interfaces. I’m mostly a back-end developer, although most of my jobs have required me to wear the hat of a designer as well. Being a hobbyist developer means that I don’t get to hire anyone to do things like UI for me. I have to do it all myself, which is both a blessing — I get to learn stuff and hopefully get better over time — and a curse — mostly in the form of actual cursing because my UI looks like shit, or doesn’t behave as expected.
Take, for example, the act of opening a simple window. In order to accomplish this you need — a window. This window is normally invisible, or off-screen somewhere so that the user doesn’t see it until it’s needed. Aside from considering whether or not to animate this window (Fade in? Fly in? Zoom in?), the second hurdle beyond design is how to get the window to show up in the first place. In this project, the player will be asked to pick an item to research based on market research that randomly selects a base item type that the population says they’ll buy if certain attributes about that item meet their (intentionally vague) demands. Once the player has decided on which demographic to appease by building their dream product, she’ll need to pick an unused research facility from the map by clicking on it. Currently, these facilities are just small, colored tokens. When the player clicks on one of these, they’ll get a UI panel popup that shows them how much it’s going to cost them to rent the facility each month.
What the user sees is “click the icon, get the window”. What I see is “holy crap where do I attach this UI? How do I get the clicking on the icon to work? How does the act of clicking on the icon tell the window to show itself? And how do I get rid of the window when they decide they don’t want this facility, or when they do choose to rent it?” The biggest hurdles have been where to put the UI, and how to get the action to trigger the UI. In Unity, the UI is now represented by actual game objects, as opposed to the “in pure code” from Unity versions gone by. This means that we can design the UI in the Scene (working) view and see it during edit-time, but it also means that all UI elements are objects in the Scene, like models and lights and audio sources. There’s a certain hierarchy that needs to exist in order for the UI to render, so there’s also a tiered structure that needs to be considered when dealing with different UI elements.
I put the rental fee UI on the facility icon itself, which makes talking between the two easier. What I found very quickly was that with more UI elements comes more complexity when trying to figure out where to put the UI and how to talk to it. Putting the rental fee UI on the icon might work now, but what if there’s a situation where I need to open that UI from somewhere not associated with the icon? I envision a master control panel that will list all research facilities currently rented and operated by the player, so she could click on an item in that list which moves the camera to that point on the map and opens the panel that explains what’s going on with that facility. None of that would be sourced from the item itself; it would need to be called from outside the item, like from a main menu or toolbar. I could add component references between the buttons — wherever they are — and their UI targets, but that results in a lot of spaghetti connections that are difficult to trace when debugging.
The answer was “abstraction” and “oversimplification”. I created a “window manager” which is nothing more than a list of windows in the system. When a window starts up, it registers itself in the master window manager list, and then either stays put, or is hidden (or moved to a point off-screen). With the window manager system attached to the Game Data Object — the global, non-destroyed, singleton object that is accessible from everywhere in the game — I can call methods like ActivateGameWindow() and pass in a name as an argument, like “ResearchRentalUI”. If that UI has self-registered and is in the management stack, then the method will find it and turn it on, activate the animation, or do whatever it needs to do in order to activate that element. This messenger systems ensures that I don’t need to have one specific element know about the existence of another specific element, so long as I don’t misspell the name of the UI element I want to send the message to.
I’m not writing this because this is some kind of revolutionary design technique, but rather because what we see on the surface isn’t always what we think we’re looking at. Sometimes things are more complex, and sometimes they’re more simplistic, and sometimes they’re way out in left field.
I’ll admit that I’ve been violating Rule #7 of Software Development by not storing my project in a version control system. Actually, I’m storing it in my OneDrive folder, which means it synchronizes across multiple computers so, you know, I can work on it in multiple locations.
The other night I booted up the project at home, but I didn’t see my most recent changes. In fact, I did, but they were duplicate copies which had been renamed to refer to the other platform on which I’d last been using them. “Oh well,” I thought. “They’re just dupes.” So I deleted them. Hard deleted them.
Turns out those files were the most recent updates, and what I had left over were the older copies. I freaked out, to the point where I downloaded an app that supposedly allowed me to undelete files (which is scary when you see how many of your files you can undelete). But when I said I hard deleted them, I mean it, so good news is that Windows does a decent job of scrubbing things that your average off-the-shelf recovery software can’t find, if that matters to you, Mr Snowden.
Needless to say, I was pissed because one of the files was my core data management scripts that contained all of my loading and saving functions. Those functions comprised the one part of the game that I felt was “complete” in that it was generic enough that I wouldn’t need to touch it again even when adding elements that needed to be saved to the overall game itself. Nice, efficient, powerful. And gone.
I spent the next session re-writing the whole thing mostly from scratch. I still had a much older copy to serve as a reference, but was missing several key methods, like the one that managed the save game manifest file (the manifest holds info on all of the actual save game files, and is what is read when you click “Load Game” to allow you to select a saved game to load). The good news is that I had just enough of a memory (and some notes) to allow me to recreate the system, but better. I feel that this new iteration is more robust even than the original, which I was a big fan of. And once I’d completed the work, I zipped up the code and stashed it somewhere safe.
So I need to get this stuff into Github, which I’ll hopefully end up doing this weekend. That way, I can avoid future costly mistakes. Learn from my sorrow, kids: Always use source control.
Listen, I’m not a gifted hobbyist when it comes to working with Unity. My approach has been to logically suss out what I want to do using my knowledge of application development, build some test cases in code, and hopefully rely on the script (that I know) far more than I would rely on whatever automation Unity offers (which is what I’m generally fuzzy on). Of course, using Unity means using Unity, so I can’t simply script my way to Nirvana; at some point I’m going to need to use the Unity Editor to Get Stuff Done ™.
Exhibit A: Animating a panel to fly in on a button press, and to fly out when I click Cancel. The goal seems relatively simple enough, and I figured I was halfway there because many moons ago I had done some work in Flash which introduced me to the concept of key frames, which are points along a timeline where properties of an object to be animated can be changed. Unity’s animation system, at it’s most basic, uses keyframes as well, so I figured that I could create an animation clip, set some keyframes and alter properties, call the Play() method from script (either SlideIn or SlideOut) when the appropriate button was pressed, and everything would work as I assumed it would.
Check out this monstrosity. Click to embiggen and feel your soul being drained as I explain how this simple task is hampered by the Power of Unity.
The top portion of the screen is my design surface. You can see the frame of the UI boundary on the left, and the panel to fly in is on the right. When we run this, that panel is outside the bounds of the camera that draws the UI, so we can call it “exit, stage right” (or left depending on whether you’re on stage or in the audi…you know what, I don’t care about this metaphor). The properties of the panel are just a whole lot of technobabble, but the important part is the bottom of the screen. That’s the “flow” of animation that I was forced to deal with. What isn’t shown is the panel that allowed me to define the animation through the use of keyframes. In that, there are two “clips”: one that moves the panel into view from right to left, and one that moves the panel out of view from left to right.
At some point, I had actually had a simple version working. I had just defined the two clips, assigned them to the panel, and was able to call them from script, by name, and it worked flawlessly. Then Unity decided to cough up a techno-hairball and screwed up a whole bunch of UI elements Just Because(tm), forcing me to rebuild a few. That messed up my animation setup, and when I attempted to recreate it, Unity decided that now it wasn’t good enough, and started throwing errors. This sent me in search of a way to animate a UI panel.
Let me tell you: there’s fuck-all for info on how to do something as simple as UI animation in Unity. Doing a search for “animation unity3d” with any additional criteria thrown in only brings back information on how to animate character models or sprites. Yeah, I get that the character is really the heart and soul of a game and it’s also pretty complicated, but does everyone understand UI animation? Am I just Extra Clueless? That’s rhetorical, by the way.
What I had to do was to create the Idle state for the panel, which means it’s not doing anything when you start, or after the panel has moved. I also created two boolean flags: IsOpen and IsClosed, and are using them to brute-force the situation. When the user clicks the OPEN button, the IsOpen is set to TRUE and IsClosed is set to FALSE, which routes the state machine to the SlideIn clip, and then back to Idle. Reversing the booleans when I click CANCEL routes to SlideOut, and then back to Idle.
I can accept this, but I really question why I have to, since I’m not using script and not Unity-proper to handle my buttons. I feel that it would be a lot easier just to build the animation clips for a GameObject, put those clips in a reference bucket on that object, and then call those clips from code to have them play. In fact, I know this can happen, because the Play() method exists, but I can’t find a straightforward tutorial on how to set up the environment in a way that allows me to refer to those clips by name, and since I did have it set up once, but was rebuffed when I tried to replicate that situation, I’m more confused than I was before.
I’ve been working on that “mystery game idea” since I mentioned it in the last post in this column, and now I want to talk a little about it.
The idea is relatively simple on paper: you are the head of a corporation in a cyberpunk universe. You have to make your company financially viable by researching, manufacturing, distributing, and marketing products. Being cyberpunk, however, it’s not just about financial warfare; it’s also about actual warfare, so you can steal and sabotage your competitor’s resources which will strike a blow to their pipelines.
And that’s the pitch.
Right now, I’ve got the very initial framework down that allows me to create a CEO and a corporation, choosing a portrait and a corporate logo. All of that saves to disk. You can also choose to load a saved game from disk. Hey, that’s been the Achilles Heel mechanic of most of my previous project attempts, so I’m super pleased that this aspect of the game is already on the books (more or less) so I can concentrate on other things.
The game moves in phases. First, you start with nothing, and need to choose your first item to work on. You’ll get a “market research” panel that will give you three random options, and what it is about current products on the market that they don’t like. Maybe one option will be an anti-cybernetic-rejection drug that should be “more potent” but also “less addictive”. Choice of item really has no bearing on anything except as a way to goad the user into picking something, and giving them a vague target to aim for: better than the attributes the panel say they dislike.
Next, you’ll need to pick a location on the map to set up an R&D facility. It costs money to rent, and you get a level 1 lab which installs the selected item to research. Research is a passive affair, but you’ll need to decide which attributes to boost and which are OK to sacrifice. Each item will have X attributes, but only a few will be relevant when trying to appease the market research subjects. In order to increase your chance of making something better than what they have now, you’ll use sliders to spend points on attributes. But in order to get those points to spend, you’ll need to decrease the sliders on other, less important attributes. If you’ve got the money, you can hire a researcher who adds permanent points to your pool that don’t require you to sacrifice anything, but you can’t hire enough to max out an attribute, only to supplement it so your other attributes don’t suck as bad as they would otherwise.
You can get a market research panel to research new products, keep manufacturing the same stable of products, concentrate on a market or diversify, hire and fire, improve the level of your facilities, and so on.
That’s about as far as I have conceptually. Beyond this, there’s ideas for manufacturing and setting a price, then getting into a market which may or may not have been represented by the initial study that you worked hard to live up to in the first place. You can improve your chances of selling even the crappiest items by crafting a killer marketing strategy by hiring celebrities or creating controversies.
The corporate warfare is something I want to include because it’s a cyberpunk staple. If you’d rather not hire a researcher, say, you can hire a street merc squad to “extract” a researcher from a rival corporation, scoring you not just a researcher but other boosts in the form of bad PR for your target opponent. Of course, they can do the same thing to your off-duty researchers, so you’ll want to hire security for your facilities which could resort in some collateral damage along the way.
There’s a lot to flesh out, including the all important “what’s the damn point” in a game where your actions all support increasing your profit, but currently for no good purpose…and no end. Maybe you’ll have to run your rivals out of business, but how? Maybe you have to reach some kind of domination scenario, but how? I know it’s not really “a game” without a win or lose condition, but there’s always a bunch of opportunities for both when we’re talking about corporate warfare.
I read in several different locations that talking about a project often times can trick the mind into believing that progress is being made, which in turn subverts any real attempts to make actual progress on the project itself. I fully embrace this explanation, since I’ve fallen victim to it on several occasions. Still, I can’t help but write something about my projects because on the other hand, seeing something in writing makes things real for me. It also acts as a log of action, something that I can look back on and remind myself what I was thinking at the time. Ideally, writing about projects would keep me honest and hold my feet to the fire, but on their own these are just words; what I’d really need would be interest, and people to keep on my case over time.
Of course, it doesn’t help that my projects — like Project Universe — are insanely complex for someone with absolutely zero game development experience. Since game dev is pretty much a black box industry, all we see is the finished product. We the consumer might be treated to some talking head video diaries from the development company which feature distant captures of monitors with code, or teasing montages of artists working on out-of-context assets, but nothing we see is really about process; that stuff is horribly boring because at the end of the day, games are made using the same processes that pump out any other widget on the planet: meetings, budgets, and a lot of solitary work done while underneath a set of headphones. My point is, I’m really good at aiming high, and have been using this site to record my progress in the hopes that it would keep me going during the times when the task seems insurmountable because of all of the things I don’t know. Everything can be learned, although there’s only so many hours in the day, and for something like Project Universe which would have required me to be designer, developer, and artist, each day would need to be stretched out to something like 60 hours for me to feel that I had enough time left in life to get done what I want to get done.
Although this is something I’ve always realized, I found that making progress negates that worry significantly, so in that vein, I’ve been thinking about what I could make that would be less ambitious, task-wise, that I might actually be able to finish. I think I might have the answer, but of course I thought that Project Universe was also an answer at one point in my life.
I’ll not go into specifics about this project just yet, since I’m only brainstorming the concept and mechanics and what I want a player to get out of the game. Some parts already make sense, but some parts are leading to blatant dead-ends for fun, replayability, or general engagement. I have to be open to the idea of throwing away ideas that don’t work, rather than stubbornly trying to force those round pegs into square holes because I don’t think I can come up with an alternative, or because I am so focused on one particular end result that I feel that I must have.
The good news is that this concept could be simple enough to exist as a boring old form on a web page. By “simple” I mean “it doesn’t need a whole lot of flashy graphics to work”. I like enticing visuals as much as the next gamer, but the idea this time is to focus on my strength, which is coding. No matter what approach I take, I don’t foresee this project needing tons of “deep” art, most of it being static, and very little being animated, if anything.
That being said, I keep coming back to thinking of this project in terms of being a mobile game, or at least a tablet game. I’m not sure that’s the way I want to go, partly because I don’t do mobile or tablet gaming myself and have little to no interest in that market, but also because I have no experience in mobile or tablet development in anything. Using Unity (naturally), I could compile for mobile platforms with relative ease (sans Apple because I’d need a Mac), but it just throws a whole curve into the equation that would effectively take the place of some of the complexity that I think I’ve already engineered out of the endeavour.
So right now, I’m going back to thinking and planning about the first steps, the goals, and parameters of the most basic tasks that I want this to accomplish. Unfortunately I’m already trying to fend off secondary and tertiary system ideas, the kinds of things that flesh out a basic game concept so that it’s more than just “pushing buttons”. Those elements will get dropped into the sidebar, and I’ll have to revisit them once I’ve got a solid grasp on the fundamentals of what I hope to accomplish.
Here’s a study in “what you don’t know and how it feels to learn it”.
I was looking at my brownstone model and thinking about how I was going to texture it. It’s not the most detailed model out there: it’s got some windows, with window frames and panes and such, and that’s about it. But unwrapping this would be a real PITA because of the natural crenelations involved in recessed building techniques.
I was looking at Substance Painter and Quixel Suite 2 because both of those supposedly allow you to just paint right on the model, or define material placeholders on your model in Blender, which you can then just “auto-replace” with proper textures (oversimplification, but I don’t really understand “PBR” enough to provide a better explanation). I thought “Wow! That’s really cool!”, but after watching a tutorial on Quixel, it looked really complex. Substance Painter seems better explained (their tutorial videos are very easy to understand, so thank you, Allegorithmic!), although more expensive.
In the course of watching Substance Painter videos, I learned a key fact about 3D modeling, and why you would want to make a high-poly and low-poly version of the same model. I had heard of this dichotomy before, but thought of it as designing for different needs. A high-poly model would be useful for stand-alone rendering like ads or showcases of a product. Using a high-poly model in a game is dangerous, as the more complex the model the more horsepower the engine has to devote to draw it. Multiply that by however many models you need to render and update in real time, and it becomes clear that high-poly models are going to have a significant cost. So designers need to make a low-poly version for real-time use in the actual game. What I never understood was that there was a connection between high and low versions until I watched the Substance Painter videos: the high-poly model — the one with all the intricate detail — serves as the template from which you generate your mapping, such as a normal map and occlusion map. You then take those maps and apply it to the low-poly model, and suddenly the low-poly model looks like the high-poly model, but with less geometry. It’s all a trick of the virtual light that makes your generic, less detailed model look like a more intricate, highly-detailed model. Mind = blown.
This was the point where I went looking for information on generating maps for my brownstone. I’d generate the maps on the detailed model so those windows on the less detailed version would be simplified, and I’d let the normal and occlusion map take over the illusion of depth. But in order to get those maps, I’d still need to unwrap the UV, which is the absolute bane of my existence. Even Blender’s “Smart UV Unwrap” method didn’t provide me with a “good” implementation that I could understand. I needed more information on how to handle this specific aspect of modeling, but a lot of the documentation on Blender is either really outdated, or not informative enough in terms of technique.
So I went back to my uber-Udemy Blender course. I’d left off at a place where they were talking about the absolute basics of using Blender, so “watching” those videos meant spending the time playing Black Desert Online on the other monitor while the instructors went over loop cuts and things like that (i.e. all the things I end up forgetting exactly at the point where I need them). The next chapter, however, was a little more in-depth. We were working on creating a bowling pin and ball. Not the most exciting models, of course, but a lot was learned: using materials, bezier curves, how to turn most anything into a sphere, and some of the more “esoteric to new modelers” concepts. The course also touched briefly on getting the models into Unity, along with creating a collider “shell” for your object so physics works correctly in the game engine. In short, good, usable techniques with examples, explained well.
This course is long, but informative and easy to follow, and that’s the bottom line here: tech teaching usually sucks real hard. When I finished up the video instruction for the day, I had a really sweet looking bowling pin and ball! I credit the instructors for knowing how to talk to an audience that knows nothing about the upcoming task without talking down to the audience that knows nothing about the upcoming task. Tech people are the worst at this kind of thing, by and large, because they know what needs to be done, but don’t always think about what needs to be done. Tech people like to always move forward, and don’t always consider the steps they need to take to do the things that are now second nature to them. When tasked with instructing someone else in how to perform as task, at least one of two things happen:
- They get all eye-rolly and condescending
- They skip a crap-load of constituent information
Everyone knows — or has been at the center of — stories of tech folks talking about how non-tech people are “stupid”. That’s a load of bullshit. No one is born with knowledge they enjoy holding over people, there’s plenty of knowledge that even the smartest people have trouble grasping, and “stupid” calls to mind people who can’t do anything. I can build a PC from parts, but I can barely do more on my car then start it and change the wiper blades. To an auto-mechanic, I might look “stupid”. To me, a mechanic who can’t figure out what an error message on his computer screen means might look “stupid”. Different strokes, people. We all have potential, if someone else can muster the patience.
But having patience is no good if we can’t articulate. Tech people are funny in that they’re always thinking current or abstract. Here’s the desired outcome, and here’s what you need to do to get it done. A lot of the Blender tutorial info I was finding took that approach. It told me what I needed to click and what it did, but never really explained why I would want to do that. “To get the desired results,” is certainly the sarcastic answer, but it’s not the answer that helps me help myself in the long run. Because tech people rarely look back to evaluate what they’ve already learned, they usually can’t give out decent advice on how to get up to speed. This has been the core issue for me in game development. I can repeat steps someone tells me I should take, but I don’t understand why I need to do it. How do the parts relate? How can I recover something if it goes south? Are there any best practices involved, and what are they? And if I run into a similar but also different situation in the future, will this technique still be applicable? I’m being given a fish, not taught how to use the fishing rod.
I enjoyed my video tutorials so much that I didn’t want to stop last night, but I had to, you know…get up and move around to avoid an embolism or something. I felt that I was really getting somewhere and learning something. I had started out wanting to accomplish “a thing”, found that I couldn’t because I didn’t have adequate training on how to accomplish “a thing”, and then found that one of the resources I had at my disposal was actually helping me learn. Not specifically about the “a thing” I wanted to accomplish at that moment, but I feel that I’m making progress, and will eventually learn enough to be able to do that “a thing” that I need to do.
I’ve been looking over the ORK Framework (ORK from here on in) recently, clicking all the buttons and checkout out the integrated help panels, and while it seems like a lot of boxes to check and forms to fill out, I think it’ll go a long way towards helping streamline development of…something. Just, something.
The difficult part is going to be coming up with the part of the game that’s not really covered by the mechanics. With Project Universe, I didn’t need to really come up with a story. I was just providing the tools that would allow the player to interact with different aspects of the game — buying, selling, shooting, discovering, etc. — and let him go on from that point. Anything I try to work on with ORK is going to require an actual narrative of some kind. Maybe.
The easiest path would be to use ORK to handle missions, inventory, characters, combat, and AI. I’d be on the hook for visuals (terrain, models, animation, audio, UI) and story, of course. Taking this route would lead to a relatively standard RPG. I would need to come up with a story and missions, and would also need to spend cash on city terrain assets, and would have to find some way to deal with character and NPC models. That last part frightens me the most, because one option would be to have a character creator with customization options and that requires a whole lot of art assets that I don’t have and don’t have the skills to create. Or I could just go the Deus Ex route and say “you are this person, and this is your story”, trends be damned.
The more difficult path would be to use ORK to handle the above, and add to it the same elements as above, but also to add ancillary systems to the mix. I’m not sure how to get access to ORK from code, but I’m sure it can be done. There’s also a framework for plugins that allow developers to create their own systems to be recognized by the framework, and to hopefully take part in ORK’s features such as loading and saving, menus, events, and variable exposure. This option means that not only do I need to tackle the “easy” paths more difficult structures, but have to figure out how to code against ORK and maybe make plugins.
The bottom line is this: no matter how “easy” any of this seems when employing shortcuts like ORK or Playmaker or other framework, there’s never an “easy” way to create a game. It’s a project, like siding a house or building a boat (a real boat). When we’re living in the house or riding in the boat, we tend to take the work that went into putting these things together for granted, and that’s part of the point of construction anyway — so we don’t all have to construct our own. It’s only when we get down to trying our hand at making something ourselves do we really gain a deeper appreciation for the difficulty and time that goes into the things we enjoy.
In looking into other Unity projects I could work on, I’ve been combing through my Asset Store library to see what cool shortcuts I’d purchased that I could use to put something together. I’ve got a smattering of core assets like models and auto-rigging solutions, but I have a few higher level helper assets like Playmaker that might help bang out something quickly.
One asset that I have is the ORK RPG Framework. This massive asset takes care of a whole host of functionality for creating an RPG including menus, enemy AI, battle systems, items, inventory, and dialog. At first blush, it’s insanely complex, and also reminded me a lot of RPG Maker VX in it’s intent. But in delving into the documentation this morning, I’ve noticed that there’s a lot of options for creating other types of RPGs beyond a Final Fantasy remake.
But what I wanted to talk about was how the developer is operating. ORK by itself is vast, and out of the box it seems like it’ll serve almost anyone in almost any RPG task they want to tackle. For anything else, the developer has opened new features to a crowdsourcing method. If a development group wants a feature, either private for their own use, or agree to include it in the public release, they can commission the developer to work on it. Even better, he suggests that if the community is hell-bent on having a specific new feature — like a grid-based combat system — then they could get together and pool their money like a small Kickstarter campaign to make it happen.
I think I approve of this method. First, it helps the developer prioritize features. Second, it helps to reduce the screaming for “can you make it do X?” because if someone wants it, they need to convince the community to get behind it and fund it unless they can and want to pony up for it by themselves (or on behalf of their company). And third, it’s a good revenue stream for the developer. The update that includes a grid combat system was priced out at $3,200, funding was met, and will be part of the public release package (which is awesome, BTW).
I can see how some folks might not take kindly to this kind of process, though. We’re trained to believe that we should only have to pay once and get everything after that — or at least that’s how many communities behave. While it’s certainly the best case scenario to get as much as possible for as little cost as possible, the long tail of a project requires fuel in the form of capital, and in light of this crowdsourcing system I can see how the “fairness” is being spread around. If the developer only relied on new purchases to fund ongoing development, at some point everyone who wants the package will have the package, and will require the developer to sell a “version upgrade”. I think this system is preferrable, because someone can pay in $5 or $10 or $100 based on how much they want a new feature. And for those who want everything to be free, they can ride the coat-tails of those who are willing and able to pay into the request.
So far it seems to be working, and although I doubt this method would work for all developers, it’s an interesting method for the community to get their voices heard and to get their pet features added into the base framework.