State of the Game - Episode 2

The current goal is to stitch together the various prototypes into a playable alpha.

This video shows off the new terrain as well as logging, mining, and basic farming. These are the basic economic loops allowing players to generate revenue. NPC behaviors are slowly being built up using Behavior Designer. 

Next up is getting the constrution of buildings up and running as well as the start of basic dialogue with the NPCs. Stay tuned for more.

Want to have input on the development? 

Come join the discord server. It's the best way to make your ideas heard!

Graphing Script - It's not exciting, but it needed to be made

A download link to my graphing asset is at the bottom of the post - if you want to try it out.

Game #2 will likely be centered around economics as well as climate (change). Deciding where to build a farm will likely be best done when looking at some climate data. Does it rain enough? Maybe too much? How hot does it get? Is the ground water polluted? Or looking at historical prices of commodities may help a player decide what type of business to pursue or how much they can afford to pay NPC employees. I don't want the game to be a data crunch fest, but data will be a part of the game. So naturally I'll be needing a way to visualize that data and graphs seem like a good way to do that. Pretty sure players don't want to read a list of float values.

Visualization - Basic line (scatter) graph

Graph Maker

I'd seen Graph Maker on the Unity Asset store and bookmarked it many months back. The reviews are pretty decent and it is definitely capable of a lot of heavy lifting. I'm aware of at least one reasonably successful game that has made use of it. So it seemed worth the risk of a few bucks. Graph maker clearly has had hundreds of hours poured into it. It's polished and feature rich.

All those features have also caused it to be fairly complicated. Each graph has several nested prefab elements each with scripts attached. The documentation is also a bit rough. As a new user the number one thing I want to know how to do is send the graph a list or array of my data and have it graph it.That's it. One simple function. So where is it?

I spent a while clicking around trying to figure out where the data was stored (turns out to be in the series prefab/script). I opened the documentation and couldn't find clear directions of how to send my data to the graph via script. I opened the scripts in search of the list or function that would import my data... Couldn't find what I was looking for.

There is a neat reflection script that can be attached to gameObjects and looks like it could do some handy stuff, but I couldn't get it to do what I wanted. All in all the asset looked way bigger than what I needed. Do I need radial graphs? I don't think so... 

The second thing I want to do is modify the appearance of the graph. The shear number of (nested) prefabs not to mention the number of settings in the main script it seemed like it was going to be a long battle to customize the looks of a graph.

So as I so often do, when I can't figure out an asset I start down the path of rolling my own asset. If you have more patience than I do, I know that Graph Maker is a good asset and will make pretty graphs for you. 

Rolling My Own

The goal of rolling my own graphing asset was to make something simple, lightweight and easy to use. As of writing this post my graphing asset has 6 prefabs and three scripts (one of which is a custom inspector to allow graph updates in edit mode - another detects mouse hovering). The prefabs largely consist of gameObjects with just an image component. A few such as "tick marks" or "axis labels" have children with Text components, but nothing gets more complex than that. Sending data to the graph is done with 1 of 3 functions. Pretty simple. 

Just send the data and let the graph do the rest.

In the end it's taken me way longer to roll my own graphing script then it would have taken to figure out Graph Maker. Is mine as pretty? No. Does mine do nice tweening animations? No. But I know how mine works and I know how to modify mine if I need to.

The feature list is short. It can switch between line (scatter) and bar graphs. The axes, points, connecting lines, and tick marks can all be tweaked in size and color. 

Bar graph of the same data as at the top of the post

Fonts, font size and font colors are all of course adjustable as well. Modification of the images was left out of the inspector/script and can be done with the prefabs. This was done for simplicity and the simple fact that changing images is less of a "tweak" than font size might be. 

I still have one feature to figure out and that's auto-scaling. Currently the axes will auto scale and adjust to fit the data, but the values displayed on the axes does not. I'd like to figure out some basic auto scaling to keep things simple - sure I can manually adjust the values in the inspector (or by script if I expose the variables or add a new function), but that's hard to do when the game is published... I like to be involved the community, but manually adjusting each player's graphs is a bit much. I'll keep the linked package up to date if anyone has ideas of how to auto scale I'd love to hear them.

Edit: The auto scaling is now working. 

Download (Free)

I may polish the asset a bit more and put it on the Unity Asset store, but that's a lot of work for not much of a return. Until then I'll happily handout a free download (box via goo.gl). Feel free to use it or modify it. Just don't flip it and sell it - don't steal my $12 in potential sales! If you do use it I'd love to hear about bugs or ways to improve it (but not bloat it). 

Not until writing this post did I realize I named my asset the same as the one I'd purchased. Oops.

Tutorials: Low Poly Snow Shader

My last post was about adding snow visualizations into Game #2. In the end I came up with a custom shader that ran faster than an asset I found on the Unity Asset Store. In my (quick) research I didn't find a tutorial showing what I needed, so I thought I'd do a quick series and show my project. The tutorial series covers the full creation of the shader (in Shader Forge) as well as a simple script to control the snow effect scene wide. 

If you want to see more details about the creation of the shader or if you'd like to try it out (download link in the video description) then check out my tutorials series. The first video is just an intro and explanation of what's to come. If you want to get to the meat then click here to skip to Video #1.

Intro video showing what will be created in the rest of the tutorial. Shader Forge: https://www.assetstore.unity3d.com/#!/content/14147?aid=1100lHSw Tutorial Assets: https://app.box.com/s/npupei7px4tjavkkg4gtbz3y3mj6b73b

Low Poly Snow Shader

With the environmental simulation getting near to finished it was time to start looking at how to visualize the weather. I'm using Tenkuko Dynamic Sky for my overall lighting and day/night cycle. It's not perfect, but makes my scenes look so much better than I could do on my own. It's worth every dollar.

Seriously. This looks good. This took about 3 clicks...

Tenkuko does a great job for general lighting it also has functionality to support rain, snow, fog and clouds. The clouds aren't perfect  and probably won't work for a low poly game. What Tenkuko doesn't have is snow accumulation. So I started doing a bit of research to find a solution. 

Global Snow

I headed over to the Unity Asset store and picked up Global Snow. It's beautiful. Truly. It supports flat shaded snow as well as two other modes that produce more realistic snow. The asset doesn't require you to change shaders or materials, but simply adds a script to your camera.

Global Snow with Flat Shaded Snow

I was seriously impressed. It took maybe 5-10 minutes of messing around with settings and I was pretty happy with how my scene looked. The bummer came when looking at the performance hit. Now a little performance hit is no big deal. The the snow scripts are not going to be used all the time. Plus the game is not an action game so a small frame rate drop is not a big deal. All the same I'm still aiming for 60+ fps on reasonable hardware.

On average I saw a 5-10 ms hit... At max settings it was sometimes 20 ms.

Full disclosure, the scene I'm running this in is huge. The terrain is roughly 2 km square and its totally NOT optimized. Meshes are not joined and no occlusion culling is being used. Many of my trees have no LOD on top of all that. Unity says it's rendering 10+ million verts, so not a tiny scene. Still a 5-10 ms hit is a lot. Not a deal breaker, but enough to make me look for another solution. The last line in the profiler is a script I'm using to control my custom shader.

If I had a smaller scene or a simpler game I'd definitely look at Global Snow as a potential snow solution. I may give it another try once my scene is more optimized too. 

Custom Shader

This is probably what I should have done first, but like a lot of us out there in game developer shaders scare me and seem like black magic. I watched a video or two and dusted off an old shader book I had. The result was the creation of a custom low poly (flat shaded) snow shader using Shader Forge to create the shader. 

If you haven't seen Shader Forge it's worth a look. The interface is all visual/nodes but it compiles as a proper shader script. This means that shaders can be shared and run on computers that don't have Shader Forge. In theory this should also make the shader run more efficiently - not sure how it would compare to a carefully coded shader. 

The final shader all wired up in shader forge.

The snow shader has height dependent snow and frost (upper left nodes). The frost essentially eases or fades in/out the snow. The shader also has a snow coverage slider that allows a selection based on normals so that snow can be just on top all over or somewhere in between (middle nodes).

Show Material Options

Producing the shader took me a handful of hours. Mostly because I'm totally new to shaders. But the result is pretty decent. Granted it's not a complex shader, but I'm still pretty happy with it. Below is a screenshot using my shader (same angle), compare it to the earlier screenshot using Global Snow.

Same angle as with Global Snow, but using my custom shader.

Is mine better? No. No way. But it is a whole lot faster. I didn't get exact numbers but at most I saw 0.5 ms difference between my shader and the standard shader (I'm rendering 10+ million verts in a very un-optimized scene). I suspect that was just random fluctuations more than anything.

Some work on the "snow texture" to give a bit more depth and variety will make the two very comparable. Probably moving the snow color just a bit away from pure white will also help.

Tutorials

I'll probably make another post, but if you're interested to see what I've done or better yet try it out and tell me how to do it better. You can check out my YouTube series on the snow shader.

Environmental Simulation Part 1

When I settled on the current game design idea a central piece was an environment simulation that would effect player experiences and that player choices could in turn effect - creating a feedback cycle.

Iteration 737 - Humidity Heat Map

The goal wasn't (and still isn't) to create an environmental simulation that was "physically accurate." The goal was to create a simulation that was an abstraction of reality or at least had some of the key features seen day to day and year to year. I wanted the player to be able to alter the world around them in a way that reflects reality but that doesn't need to be 100% realistic. 

Key Features:

  • Day to day temperature swings
  • Seasonal temperature swings
  • Wind to transport moisture
  • Water/Rain cycle
  • CO2 effects
  • Pollution accumulation and transport
  • Runs off the main thread

Building Blocks

The first step in creating the simulation was to break up the environment into a series of blocks. Each box would have it's own set of environmental variables (temperature, humidity, ground water, wind, etc). These "climate blocks" would interact with it's neighbors to create localized weather and also to allow local variances such as terrain height and cloud density to impact the weather. 

Test Terrain with Climate Blocks

As the simulation developed and more complex interactions were add a few changes/additions to the climate blocks were needed. The first critical piece was the addition of an "atmosphere block" on top of each climate block. The atmosphere block is simulated air space above that often has a different temperature than the air on the ground/ocean. This allowed for up and down drafts that could help move clouds and cause an on or off shore wind depending on the season (more about this later).  Without an onshore wind clouds and more importantly rain rarely make it to the land.

A second key addition was the classification of terrain types. At the time of writing this the simulation is only using three types of terrain ocean, grassland and mountains. This largely controls the "target" temperature of climate block and in the case of the ocean maintains a constant saturation of ground water. Oceans have moderate target temps with smaller seasonal and daily fluctuations. Grasslands have a higher target temp than the mountains but both have larger daily and seasonal fluctuations than the ocean.

Daily and Seasonal Temperatures

Seasonal sun intensity is controlled by an animation curve that is sinusoidal in shape. Max values occurring during the "summer" and of course minimum values occurring during the "winter." A second curve was used for daily fluctuations. The curves are currently identical... That may change in the future. 

At first these curves were used and tuned to be a true energy flux with energy being added during the day and energy lost during the night. While more physically accurate and potentially allowing for more emergent weather, it also made it far more difficult to tune and balance. After significant testing and tuning this method was abandoned for a more controlled method. 

Each terrain type has a median temperature that serves as a target temperature. There are also values for seasonal and daily fluctuations of that temperature.  This means that median temperatures + seasonal flux + daily flux is roughly the high temp and likewise median temperature - seasonal flux - daily flux is roughly the low temp. Variance from this is caused by the connection of neighbors and other factors. 

One of the other factors that adds some variability is the average height of the terrain. In the real world the higher the terrain the cooler the air. To reflect this each climate block samples the terrain height at multiple points and calculates an average height. From this the median temperature is adjusted slightly. This provides variation in the climate that (hopefully) lends itself to more interesting and emergent weather.

Wind

Wind in the simulation does not  have a physical presence and is simply a Vector3 that stores the wind velocity. The wind for an individual climate block is calculated based on the temperatures of the neighboring climate blocks, including the upper atmosphere. The inclusion of the upper atmosphere allows up and down drafts which allows for onshore or offshore breezes (as mentioned above). 

To calculate the wind the simulation calculates a temperature difference between the climate block and a neighbor and then multiplies that by a vector that goes from the climate block to the neighbor. Final direction (sign) of the wind is based on blowing from hot to cold. 

The simulation sums all the winds due to neighbors to arrive at a (nearly) final wind value.

A prevailing wind is then added. This allows larger global winds to be added to create larger and different weather patterns. The strength of the prevailing wind is a tune-able variable. Current testing is with an in/out pattern that helps to blow clouds away from land in the summer. 

An early WEather Prototype

After the prevailing wind is added the vector is normalized. There was some debate about normalizing the wind...  In the end the choice was made to keep the normalization as this meant that clouds always would have some wind. It also prevents unrealistically large or small winds that become problematic when trying to transport clouds/moisture.

The final step is a check on the vertical component of the wind. Since the upper atmosphere is often at a very different temperature it can therefore be the dominant contribution to the wind. This is a problem due to only simulating two layers of atmosphere rather than more layers or the ideal of a continuous atmosphere. Effectively the vertical component is clamped to a range between -0.5 and 0.5. This helps to keep clouds generally moving horizontally.

Additional controls are needed to avoid the clouds going too high or going through the ground. The altitude of the clouds is mostly visual as the horizontal location determines where clouds can deliver rain. Because of the this a simple min and max altitude are set. Clouds check against these values and degrees of freedom are restricted in the rigidbody to prevent clouds from going outside the bounds. Checks on vertical velocity are also necessary to allow the clouds to move away from the limits. 

Continued in Part 2

In Part 2 I'll discuss the most difficult part (so far) of the simulation that being the Water and Rain Cycle. Or more specifically the balancing of that cycle.