Feb 19, 2016

Suzy Cube Update: Friday February 19, 2016

#suzycube #gamedev #indiedev #madewithunity 

This week, I concentrated on background tasks. Ha! I've been working on backgrounds... funny! I also spent all of yesterday doing something really stupid that felt so good to finally do!

I've been on the fence since starting work on Suzy Cube about whether or not I should actually include background of any kind beyond a few decorative objects outside the playable areas. But after some experimentation, I found a method for creating skybox textures allowing me to populate the outside of levels quite efficiently.


Think Inside the Box

What is a skybox? It's a term used to describe very simple geometry (not necessarily a box) which is usually textured to look like a sky and landscape which appears to surround a 3D scene. The skybox is rendered such that it always looks infinitely far away from the camera. This allows artists to fill in everything beyond a level's actual 3D geometry with what appears to lie beyond. The great advantage of using a skybox is that all the detail comes from an image, so no matter how detailed your background looks it's no more expensive to render.


Using a Wrench as a Hammer

In order to easily create the necessary skybox textures for Suzy Cube, I've been re-purposing Unity's Reflection Probes system. If you are curious, you can check out the Unity documentation on Reflection Probes. What's more important here, is the fact that a reflection probe essentially renders everything around it into a texture that is, almost, exactly the right format for use as a skybox!

In order to leverage this system, I've simply been building custom background rendering scenes.

Background scene used for Level 1-1
Here, you can see what the background rendering scene looks like for Level 1-1. I build some floating islands out of the same blocks I use to design the levels, populated the surroundings with boxy clouds and put a big blocky sun up in the sky. In order to fill in the sky colour, I also created a custom skybox shader using ShaderForge which allows me to define things like the top, bottom and horizon colours as well as the height and diffusion of the horizon.

Reflection Probe at the centre of the scene
In order to render the background to a texture, I simply placed a refection probe dab smack in the centre of the scene. The reflection probe essentially acts like a mirrored ball rendering everything that's visible from its location. This generates a perfect skybox of the whole scene.

Levels with different lighting and settings need different skyboxes, of course. Here are some of the other ones I've created so far.

Forest themed skybox
The forested background of Level 1-2 really gives a sense of running around amongst the trees.


Desert themed skybox
 Notice how the distant features further exaggerate the sense of height and distance on Level 1-3.


Sphinx!
And players are treated to a surprise as the camera swings around to reveal a sphinx in the background during the level's ending sequence.

Stupid? Worth It!

And now for the stupid thing. I rewired how inputs are handled in the game in order to play nice with InControl's default install location.

Why was this a dumb thing to do? It was stupid to do because GDC is less than a month away and I'm still not done gussying up World 1 and really shouldn't be spending my time on stuff which has no noticeable effect on the game.

Why did it feel so good? In order to be able to integrate InControl, which is written in C#, into my project, which is written in JavaScript, I had to move InControl files from their default locations in the project to special folders. Without getting into it, the major problem this caused was to make it incredibly tedious and error prone to try to keep InControl up to date as I couldn't simply update it from within Unity. In the end, I had simply stopped updating it. The changes I made yesterday now allow InControl to rest peacefully in it's default installation location while still being able to relay pertinent data to the rest of my game.

The Long Version

If you are not interested in the details of how I did this, feel free to skip this bit.
So, the major issue I've been having with using InControl is the fact that, in Unity, in order for scripts of different languages to be able to reference each other's objects, one of them must be placed in a special folder, the Plugins folder. Any script in the Plugins folder can be accessed by any other script in the project regardless of language. The problem with InControl is that it doesn't install to the Plugins folder. The necessary scripts can be moved to the Plugins folder to make everything work, but this is exactly what makes keeping InControl up to date after the fact such a problem.

Enter SendMessage! The SendMessage family of Unity engine methods allow a script to call a function or method in another script indirectly. You can read more about SendMessage in the Unity documentation. Now, sending a function call this way is less efficient than calling the function directly, but it has the advantage of being able to transcend the language barrier between scripts in Unity since SendMessage is an engine function which takes care of finding appropriately named methods or functions on the target object and calling them itself.

So, in order to get what I need out of InControl, I ended up creating a system which uses two intermediary scripts, one Input Handler, written in JavaScript, and one InControl Relay, written in C#. All inputs in the game go through the Input Handler. When a game script wants to know the state of any particular input, the script will call the appropriate function on the Input Handler e.g. IsJumpButtonDown(). The Input Hander, in turn, sends a message to the InControl Relay which gets the information from InControl then sends a message back to the Input Handler with the current state of the jump button. With this info in hand, the Input Handler can now return the state of the jump button to the game script which requested it.

I'm sure this is not the most efficient way to solve my little InControl problem, so if smarter folks than me can think of a better way, please share it!

And on that note, it's back to more decoration and making a few last minute fixes to the World 1 levels before DGC in a few weeks. See you all next time!

No comments:

Post a Comment