Blender – Custom Bevels

This week for my game called The Gap I’ve been doing some house components. The game is set in the suburbs and there will be a lot of house interiors. In what I envision to be the opening scene of the game your main character wakes in his or her bedroom alive with excitement and ready to explore the world. Which has little to do with cornices but it’s these details that make the game look like a world and adds to the immersion.

So here is an example of a cornice that I have made in Blender using the Bevel Modifier.

The Cornice using a Vector Group and Custom Bevel

This starts as a cube with about a quarter cut out of the form and a reduced height. But any straight edge will do. First use the edge select to assign all the relevant parts you want to bevel into a Vector Group. (Select the edge and in the object data panel use the “assign” button under the Vector Group section). Then you add the Bevel Modifier and as you can see in the image above you use the Limit Method by Vector Group and then add your new Vector Group you just assigned. Choose Custom Bevel and use either one of the presets or use the graphing tool window at the bottom to create your own bevel shape. There are a couple of nice cornice style presets in that section to get you started. (It helps to play round with the Amount and Segments section at the top to improve the look – also try Smooth Shading on the object).

Below is a Window frame I used the same technique on but with a different profile. I used ctrl+R to make some loop cuts around the inside of my window frame and used the edge select to assign the cuts to a Vector Group. Then again I used a Bevel Modifier to make a custom set of ridges around the window frame to make it look like the fittings of the aluminium framing around the glazing of the window.

Custom Bevel on a Loop Cut to make Window Mouldings

You can see I also added a normal Bevel Modifier to the edge of Window Sill to create the outer wall shape where the rain runs away from the window frame.

I did a quick mock up in Unity to see how they performed under the often difficult lighting environment of the game engine. As you can see below by the shadows on the walls and spot light on the floor it’s not an ideal set up and the cornices are looking pretty crap. At the top of the room on the back wall I have two longer cornice pieces and a corner piece is visible as well. The two at the back are picking up different light sources and one looks lighter than the other. They are clearly three separate objects and not one nice clean line. It might help to add some more surface geometry to the longer pieces so they are not just one long face (loop cuts or subdivisions). Alternatively I could measure them out to fit the room exactly and meet in the corners – but then I would have to make multiple lengths instead of a more modular re-usable approach.

Cornices under lighting conditions in Unity

Character Design

The other thing I did this week that was actually productive is some more character designs. This one is Hippo Boy catching a football and a couple of different shading styles (still playing with Clip Studio and still enjoying it). Next up I’m thinking about all the ways I can program a mugby style football game.

Hippo Boy
Pop Style Hippo Boy

More Gaps

This is more concept art for a protagonist in the new project called The Gap. Okapi Boy – I have always loved Okapi’s. They are shy and remained hidden from the world in the deepest parts of the jungle until they were discovered in the 50’s. Beautiful Zebra like patterns on skin like a Deer. This is a deeply peaceful animal with large soulful eyes. He dreams and offers advice but you have to seek him out and finding him is not always easy or straightforward. In The Gap you get the chance to play as the Okapi for part of the story.

Okapi Boy

There used to be a great example of this rare creature in the Melbourne Museum Taxidermy collection (which I used to love but has now sadly been taken off the exhibit floor). You can take a virtual tour of the old “Wild” exhibition here.

I have a LOT more concept art to do as I want to get a very clear picture of my characters before I start modelling.

I also stared working on the programming for the game. One element I want to include in the story is a “mini-game” called Fox and Geese. It’s played on a chess board and was one of the first games I remember my dad teaching me how to play. It’s pretty straightforward and uses a chess board and pawns. Four white pawns are the Geese who can only move forward and diagonally one row at a time. The Fox is a black pawn that can move diagonally one space at a time in any direction. Moves are taken in turn and the aim of the game is for either the Fox to break the line of Geese or the Geese to “capture” the Fox so that he cannot move.

Fox And Geese

It’s early days yet with only the board set up and pawn selection scripts started but it was actually pretty fun setting up the programming that took care of the board. When you learn programming you get to do lots of arrays and nothing screams “ARRAY” like a chess board. So it’s kind of nice to use one of those basic skills that you use in all programming in such a nice simple example. You get to add a little interest to the basic array with the inclusion of alternating colours. Here is the code below:

using UnityEngine;

public class FnG_MakeBoard : MonoBehaviour
{
    public GameObject boardPiece;
    public Vector3[] positions;

    // Start is called before the first frame update
    void Start()
    {
        positions = new Vector3[64];
        float start_x_pos = -1.75f;
        float start_y_pos = -1.75f;
        float rowcount = 0f;
        float linecount = 0f;


        for (int i = 0; i < positions.Length; i++)
        {
            positions[i] = new Vector3(start_x_pos, start_y_pos, 0f);
            start_x_pos += 0.5f;
            rowcount += 1;

            if (rowcount == 8)
            {
                start_x_pos = -1.75f;
                start_y_pos += 0.5f;
                rowcount = 0f;
                linecount++;
            }

            Instantiate(boardPiece, positions[i], Quaternion.identity);
            Color32 myRed = new Color32(185, 48, 48, 255);
            Color32 myGray = new Color32(106, 106, 106, 255);
            if (i % 2 == 0)
            {
                if (linecount % 2 == 0)
                {
                    boardPiece.GetComponent<SpriteRenderer>().color = myGray;
                }
                if (linecount % 2 != 0)
                {
                    boardPiece.GetComponent<SpriteRenderer>().color = myRed;
                }
            }
            if (i % 2 != 0)
            {
                if (linecount % 2 == 0)
                {
                    boardPiece.GetComponent<SpriteRenderer>().color = myRed;
                }
                if (linecount % 2 != 0)
                {
                    boardPiece.GetComponent<SpriteRenderer>().color = myGray;
                }
            }
        }
    }

Vector Maths with Unity Gizmos

It’s really nice to get a game finally published. Endless Elevator is now on the Google Play Store so I’ve been planning and experimenting and just plain playing around with Unity and Game Ideas before I start a new project. It’s kind of like a holiday.

I like maths and I also like visualising it with Unity. This little project is one of the simplest types of maths that is generally associated with game programming and that’s adding and subtracting vectors and getting the distance between two vectors.

These sorts of functions are endlessly useful. They answer questions like: How far away is my target? Is my Player going to fall off the platform? Can I jump between two platforms? And so on and so on.

What I like about this one is that it highlights two things. 1. The difference between a player and a target’s perspective (in this project I nominate the circle as the player and the cylinder as the target), and 2. calculating the magnitude or distance between them.

To calculate the distance (magnitude) between two points you take the square root of the square of the x and y values. Which sounds a little complicated but is really just making a square the size and length of your x, and adding that to a square the size of your y, and then getting the square root of the total size of that square.

This is how it looks in the Scene View:

How it works

The project is really easy to set up. All you need is an Empty Game Object to hold the script and two other objects. I used a Capsule and a Sphere. Drag the two objects into the public Transform components on the script.

The Project Hierarchy and Properties of the Script

Here is the reproduced script below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;
    
public class GridGizmo : MonoBehaviour
{

    public Transform circle;
    public Transform capsule;
    public Vector3 differenceToCapsule;
    public Vector3 differenceToCircle;
    public float magnitude;

    void Update()
    {
        differenceToCapsule = capsule.position - circle.position;
        differenceToCircle = circle.position - capsule.position;
        /*
           Magnitude of a Vector (Length of the Vector)
           We use Pythagoras' theorem to calculate it:
           |a| = √( x2 + y2 )
        */
        magnitude = Mathf.Sqrt(Mathf.Pow(differenceToCapsule.x, 2) + Mathf.Pow(differenceToCapsule.y, 2));
    }


    public void OnDrawGizmos()
    {

        // Grid Number Labels
        for (int i = -10; i < 11; i++)
        {
        UnityEditor.Handles.Label(new Vector3(0f, i, 0f), "" + i);
        }

        for (int i = -20; i < 21; i++)
        {

            UnityEditor.Handles.Label(new Vector3(i, 0f, 0f), "" + i);
        }

        // Labels of Objects
        UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y, circle.position.z), "POSI: " + circle.transform.position);
        UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y - 0.5f, circle.position.z), "DIFF: " + differenceToCapsule);
        UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y - 1f, circle.position.z), "Magnitude: " + magnitude);

        UnityEditor.Handles.Label(new Vector3(capsule.position.x + 1, capsule.position.y, capsule.transform.position.z), "POSI: " + capsule.transform.position);
        UnityEditor.Handles.Label(new Vector3(capsule.position.x + 1, capsule.position.y - 0.5f, capsule.transform.position.z), "DIFF: " + differenceToCircle);

        // The line
        Gizmos.color = Color.blue;
        Gizmos.DrawLine(circle.position, capsule.position);
    }
}

As I mentioned above I do like mathy things in Unity. Here are some of the other one’s I’ve done which are a bit more complicated. I find them really really useful to cement those ideas that I should know back to front but always forget exactly how they work.

Unity – Unable to update the SDK. Please run the SDK Manager manually.

I had this problem during a build this week and figured I’d better document it 1. In case anyone else needs to do it and 2. So I don’t forget it myself for next time.

I’m running Unity 2019.4.1f1 and doing the final few Beta builds for the game I’m just about to release called Endless Elevator. (If you want a quick peek before it’s released the beta has a few more days to run). I uploaded a new build to the Google Play Developer Console and noticed a new message saying something along the lines that API 20 Support was going to be discontinued soon and to check my API minimum levels. I did this and also noticed that I hadn’t updated my game’s API support for the latest releases (API 29 and 30) .

I tried to update it from within the Player Settings of Unity:

This is where I encountered the problem of not being able to run the SDK update from within Unity (you can see API 29 & 30 are displayed differently)

… and after some time got a pop up message:

“Unable to update the SDK. Please run the SDK Manager manually to make sure you have the latest set of tools and the required platforms installed.”

I had not idea what it meant by “manually” so I went into my local copy of the Android Development Studio and performed a full update of all the APIs’ and Tool packs. This didn’t help. Probably because I’d forgotten that the Unity version I was running had it’s own set of API’s in another location.

This is where I found it: C:\Program Files\Unity\Hub\Editor\2019.4.1f1\ Editor\Data\PlaybackEngines\AndroidPlayer\SDK\tools\bin\

This is how I ran it manually from the Windows Command Prompt (cmd.exe):

“C:\Program Files\Unity\Hub\Editor\2019.4.1f1\Editor\ Data\PlaybackEngines\ AndroidPlayer\SDK\tools\bin\sdkmanager.bat” “platforms;android-29”

and

“C:\Program Files\Unity\Hub\Editor\2019.4.1f1\Editor\ Data\PlaybackEngines\AndroidPlayer\SDK\tools\bin\sdkmanager.bat” “platforms;android-30”

First time I ran this I had to accept the licence agreement (Y|n) from the command prompt and it seems that this was the problem. I’m guessing that the internal Unity update function didn’t allow for the licence prompt and was timing out.

I did some googling around and found a few examples of this issue – one person said they had to create a repositories.cfg file in their C:\<users>\.android folder (I already had one so not sure if this step is required).

Anyway fun days and looking forward to releasing the game later next week.

Endless Elevator – Last Week of Beta Testing

Hi Harmony here,

I’d like to thank the wonderful Beta Testers who have signed up for our Open Beta of Endless Elevator over the last month. I was really surprised how many people responded to our call and very grateful to all those who provided feedback.

The Open Beta is still running for another week so there is still time to try the pre-release game: https://play.google.com/apps/testing/com.ZuluOneZero.EndlessElevator

Then head over to our Beta Landing Page if you want to give us some feedback.

http://www.zuluonezero.net/endless-elevator-beta/

Your feedback helps us make a better game – thank you!

One feature of our Beta Testing was opening multiple channels to provide users to get back to us. Not only did we use the Google Play Beta Feedback and Stars system but we also took feedback on email and through social media. One new thing we did was to incorporate a chat channel on our Beta Landing Page where users could provide anonymous feedback directly on to our web site. I feel that the anonymity of this format was a really important source of quality comments for us.

Our Chat Page

Happy Playing – Harmony Out.

Unity Audio vs Wwise

To start with I wanted to do a general investigation into Wwise the integrated audio package for Unity by AudioKinetic. When I started working through it I figured it would be more interesting to look at Wwise in comparison to Unity’s own audio API and mixer components which have been around since Unity 5.

To do that I’m going to compare a game in three different builds. Build one is it’s original state with simple scripts that run an AudioSource.Play() method. The Second build I will add another layer of complexity by using the Unity built in Mixer and see if there are any differences or advantages. Lastly I’ll redo the project with the Wwise API and investigate how that impacts build size and project complexity and weigh it up against the previous two builds. Mostly I’m looking for difference in performance between the three builds, build size and complexity, and weighing that up against ease of implementation and flexibility.

I refreshed an old project called “MusicVisualiser”that I started for my Five Games in Ten Weeks Challenge. The game is like a singing solar system. There is a bunch of “planets” in the night sky that play a set piece of music when clicked. It’s a really simple concept and project but I think it will work for this comparison as the parameters can be limited to just a few audio tracks but we can play with spacing and roll-off and other advanced audio features.

Let’s have a look at the game first.

These “planets” are simple native Unity sphere meshes with an Audio Source component and a particle system that’s triggered when it’s clicked. You can see in the Audio Source that we are not using a Mixer for Output and all the Audio sources compete for resources and play at their default volume and priority.

The PlayMe script just takes in the AudioSource and plays it:

   public AudioSource my_sound;
        
  if (Input.GetMouseButtonDown(0))
  {
      RaycastHit hitInfo;
      target = GetClickedObject(out hitInfo);
      if (target != null && target.name == my_name)
      {
          _mouseState = true;
          screenSpace = Camera.main.WorldToScreenPoint(target.transform.position);
          offset = target.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));

          my_sound.Play();   // This is the Audio Component!
          var expl1 = GetComponent<ParticleSystem>();
          expl1.Play();
      }
  }

Pretty simple right. This is what the project looks like in the Profiler when it’s running and being actively engaged with. At that point we are looking at two Audio Sources are playing:

This is the build size from the Editor Log with our Audio Files broken out:

Build Report (Audio.Play)
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 547.5 kb 1.4%
Shaders 188.0 kb 0.5%
Other Assets 1.4 kb 0.0%
Levels 38.3 kb 0.1%
Scripts 941.9 kb 2.4%
Included DLLs 3.9 mb 10.2%
File headers 9.3 kb 0.0%
Complete size 38.6 mb 100.0%

Used Assets and files from the Resources folder, sorted by uncompressed size:
204.3 kb 0.5% Assets/SomethingLurks_AAS.wav
164.5 kb 0.4% Assets/Step2Down_AAS.wav
136.9 kb 0.3% Assets/Underwater_AAS.wav
41.8 kb 0.1% Assets/M1_M12_37_ThumPiano_Aflat1.wav

Unity Audio with Mixer

Now we add in the Mixer component to the project:

Then add a couple of Channels to the Mixer to split the audio between left and right. Then the Audio Sources are dropped into one or another of the Mixer Channels:

Adding the Mixer as the Output source

Next for bit more interest I added some effects in the Mixer. Here is where we see the advantages of using the Unity Mixer. Sounds can be manipulated in complex ways and the Audio Output chain be defined with presets and levels etc.

If we have a look at our Profiler while running with the new component we cannot really see any great differences. The ‘Others’ section of the CPU Usage is a bit higher and the Garbage Collector in the Memory is pumping regularly but the Audio Stats look pretty much unchanged:

Profiler Mixer

Mind you this is a fairly low utilising game so we might get wildly different stats if we were really putting the system under the pump but I’m not performance testing here just comparing run states between the two builds.

Next if we build the game and have a look at the Editor Log the only thing that’s changed here is that the “Other Assets” size is a KB higher (Complete size has not been changed):

Build Report (Mixer)
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 547.5 kb 1.4%
Shaders 188.0 kb 0.5%
Other Assets 2.3 kb 0.0%
Levels 38.3 kb 0.1%
Scripts 941.9 kb 2.4%
Included DLLs 3.9 mb 10.2%
File headers 9.3 kb 0.0%
Complete size 38.6 mb 100.0%

Unity with Wwise

Next we are going to add Wwise to the Project. This is the basic workflow. In the Wwise Launcher we register our project and on the first tab we are presented with three Hierarchies.

Project Audio Explorer in Wwise

The Master-Mixer Hierarchy – does what it says.
The Actor-Mixor Hierarchy – where most of your game audio develops (use the SoundSFX defaults).
Interactive Music Hierarchy – other stuff we won’t get into.

Events Tab

The next tab along is the events tab where you link your audio to game events. You can define your event here (use the default work unit).
Once you got the event there you can associate the event with the audio in the Action List.

SoundBank Tab – this is the bit that get’s imported into your project.

Next you generate a SoundBank with Wwise that includes your audio and the code for the API calls to trigger sounds. You export that SoundBank into your game engine and link up the calls in your code.

To Get Started with Wwise

To get started make an account with Audiokinetic and download the Wwise Launcher. The Integration package for Unity can be downloaded and installed directly from the WWise Launcher.

In the Wwise Launcher there is a WWISE tab that you can install and start the application from. Once you open it up you need to register your project within the launcher so Wwise can track you 🙂 ( click on the key icon next to your Wwise project and select ‘Register your Project to obtain a License’). Wise will run in Trial mode which restricts the SoundBank content to 200 media assets and cannot be used for Commercial purposes. Pricing for licensing is on their site but this is not a sales piece so if you want it you can look it up.

There are a bunch of plugins by Audiokinetic and their partners available and also Community offerings like AudioRain a dedicated rain synth with 60 procedurally generated presets for rain. What’s not to love about that!

There is a Wwise SDK for authoring your own plugins and a Wwise API which allows you to integrate into any engine, tool or application.

Audiokinetic do certifications that covers audio integration workflows,
mixing virtual soundscapes, working with sound triggering systems, and performance optimisation :
https://www.audiokinetic.com/learn/certifications/

Basically in Wwise you let the Launcher do all the setting up for you. You will install the Wwise binaries from here and manage your platform versions. Projects can be integrated here and if you don’t have the necessary plugins installed the Wwise Launcher will install them for you.

Integrating the MusicVisualiser project with Wwise.
This is how big the Wwise Integration packages and binaries are.
Applying…
Done!

That’s basically it for the set up of Wwise and Integration with your Project. Next up we will have a look at what this has done to the Unity Console.

Wwise in Unity

First thing we see is a bunch of errors that can be safely ignored. As we did not perform any configuration of our project in Wwise with audio files and events there was no SoundBank to generate yet.

Unity – Initial Errors can be ignored if you have not generated your SoundBank yet.

In the Unity Console we have a new tab in our editor. The Wwise Picker Tab contains all the elements of the Wwise project that have been imported with the project integration. There is also a Wwise Global Game Object in the Unity Hierarchy and all the Wwise folders in the Assets folder.

Unity Editor
The WwiseGlobal Game Object

Under the Component pull down there is a whole slew of Ak (AudioKinetic) options.

Wwise Components.
Wwise Configuration Settings.

I know there has been a lot of “show and tell” in this post but I’m going to keep going and show the process of importing the audio into the Wwise Project, creating Events, and Generating the SoundBank.

Working in Wwise

In the Wwise Project Explorer I right click on the Default Work Unit and import the audio files that were part of my project. (I’ve stripped the raw files out of my project for now and removed all the Mixer components and etc.).

Importing Audio Files into the Wwise Project.
This is what the files look like.
Right click on the file to create a new Event (which can be called in the Unity code).
Here is the event created for “Play”.
And all my “Play” events.

Finally a SoundBank is generated from which the Unity project can access the sound files through the AudioKinetic API.

Generating a SoundBank

Wwise Audio in Unity

When we go back to our Unity Editor and Refresh the Project and Generate SoudBanks we are presented with the following in the Wwise Picker. We can now access these files and and drag them on to our game objects directly. It’s that simple. Drag a sound from the Picker onto a Game Object and it automagically creates a component that is immediately accessible from within the editor.

The new audio imported into the Wwise Picker.

Below the Play_Underwater_AAS event and audio file has been added to the Sphere Game Object.

The Trigger, Actions, and Callbacks can all be configured and access through the API. In my case I easily integrated the functionality I wanted with only one line change to my attached PlayMe.cs script that we looked at above. So now instead of my audio coming from the AudioSource component referenced by my_sound the audio is played by the AKSoundEngine.PostEvent.

            //my_sound.Play();
            AkSoundEngine.PostEvent("Play_Underwater_AAS", this.gameObject);

Actually getting Wwise installed and set up and integrated with my Project was very very easy but not without bumps. It takes a very long time for packages to download and I had a bit of trouble upgrading my Wwise Launcher from an old version (it got stuck! and I had to remove it by hand and re-install). When I did have issues I got some very excellent help from AudioKinetic and after logging a case was emailed directly by a real person (which honestly was so surprising and wonderful to get that kind of support from a company when I’m on a trial license with no formal support agreement or rights).

So lets have a look at the differences in performance and package size. The first thing you notice with the Profiler below is that there is very little difference in performance but we can no longer see our audio stats as it’s been abstracted away from the Unity Engine. The Graph still shows the resources being used by Audio and the Total Audio CPU seems to be up to a third lower than the native Unity Audio statistics. It looks like it’s being clamped at just over 1.2. MB instead of regular peaks over 3 MB.

Profiler with Wwise Audio running.

The Build Report is only a couple of MB larger for the total project size:

Build Report
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 0.0 kb 0.0%
Shaders 188.0 kb 0.5%
Other Assets 7.3 kb 0.0%
Levels 38.5 kb 0.1%
Scripts 1.3 mb 3.1%
Included DLLs 3.9 mb 9.7%
File headers 13.2 kb 0.0%
Complete size 40.5 mb 100.0%

Basically a 2 MB difference! The Sounds have been extracted away as a file in the Build Report and we assume they are now part of “Other Assets” above.

I’m kinda blown away by how how little additional file size there is to the build considering the additional libraries code and available complexity that Wwise adds. There is literally a plethora of options and effects that we can play with in the Wwise package. It’s a bit like the excitement I got after the install of my first real Audio DAW. The scope is part boggling and part fantastical wonder at where we can go next. (Audio does get me unusually stimulated but that’s to be expected and tempered accordingly).

The questions I wanted to answer with this whole experiment was 1. Would including an audio middleware like Wwise make my Project more complex and difficult to manage? 2. Would the added Package make my build much larger? and 3. Would the performance of the Audio package be as good as the simple Unity Audio API? The answers are: No. No, and Yes. So I’m pretty happy with that and if the cost point of using the licensed version of Wwise is balanced out against the advantages of using it in the total cost of the Project then I would most definitely one hundred percent go for it.

The Coin Flip

Ah the coin flip! Simple easy and fun. The mechanism is a platformer mainstay. You run over a spinning coin (it glitters, it calls you) it pops into the air, and it’s yours!

The Endless Elevator Coin Flip !

This is how we do it…

There is a Rigidbody and Collider on both the coin and the player character. You can clearly see the spinning frame of the coin collider in the .gif above.

The collider acts as a trigger which is being listened for by our script which executes the “pop”.

The coin has a spinning script (and also a magnetic feature as a bonus for later).

The player has a couple of behaviours that handles the trigger and action.

The coin scripts – note the use of the slider to get the spinning speed just right.

Here we have the coin’s Rigidbody and Collider settings:

The Rigidbody isKinematic and the Collider is a Trigger

This is the script we use for spinning:

public class spinCoin : MonoBehaviour {

    [Range(0.0F, 500.0F)]
    public float speed;
	
	// Update is called once per frame
	void Update () {
        transform.Rotate(Vector3.up * speed * Time.deltaTime);
    }
}

Simple and sweet.

This is the function that that handles the collision and the pop into the air! (It’s part of our character behaviours).

    void OnTriggerEnter(Collider otherObj)
    {
        if (otherObj.name == "Coin(Clone)")
        {
            coins++;
            var coin_txt = coins.ToString();
            coinsText.text = "Coins: " + coin_txt;
            Rigidbody riji = otherObj.GetComponentInParent<Rigidbody>();
            riji.useGravity = true;
            riji.isKinematic = false;
            riji.AddForce(Vector3.up * 40f,  ForceMode.Impulse);
            Destroy(otherObj.gameObject, 0.4f);
        }
     }

First of all we are incrementing our coin total variables and screen display.

The mesh for the coin is part of a child component so we need to call the Rigidbody attached to the parent object.

We set gravity to true so that it falls back down after adding the force and set isKinematic to false so we can use it’s mass to fall.

After a very short flight we destroy it (0.4 seconds).

As an added bonus here is the other coin behaviour for when a magnet power up is used in the game.

    private void OnTriggerEnter(Collider col)
    {
        colName = col.gameObject.name;
        float step = speed * Time.deltaTime; // calculate distance to move

        if (colName == "chr_spy2Paintedv2")
        {
            transform.position = Vector3.MoveTowards(transform.position, col.gameObject.transform.position, step);
        }
    }

This is when we make the collider really big on the coin. If the player gets in range of the collider then the coin moves like a magnet towards him. Which is kinda fun when there is lots of coins around and you feel like a millionaire just by standing around.

Demo Text Adventure Game Released on Google Play

Hi Harmony here….

We released the demo game for our Text Adventure framework on the Google Play Store this week.

https://play.google.com/store/apps/details?id=com.ZuluOneZero.AdventureText


The Code for the Project is available on GITHUB:

https://github.com/zuluonezero/AdventureText

Quick Start Instructions for building a 2D Unity project are available on the README.

More detailed information is available in the ZuluOneZero – DevBlog.

See our posts about the development of this game and more information on how to configure the project: 

I hope you enjoy playing with it.

If you have any questions or need support you can email us at zuluonezero.z10@gmail.com.

Harmony out…

Getting a Foot in the Door of Game Design

First of all – sorry about the misleading title – this post is about getting the doors working in the Endless Elevator game that we are currently developing. I thought it was a good pun and that as this post is all about our development process that it wasn’t too bad. The only career advice I got is just to start making games…any games.

You’d think making a door that opens and closes would be a pretty simple thing to do but surprisingly it wasn’t.

I designed and built some 3D models of building components in MagicaVoxel and exported them as .obj files. I use MagicaVoxel because it’s free and really quick and simple to use. When I model components I can be sure that they are all exactly the same scale and that all the different bits (no matter when I made them) are going to fit together without any hassle. But the models are not optimised for game engines as they have a reasonably high poly count due to the modelling process within the program. Most of the models come out with heaps of unnecessary triangles that need to be managed first. In most cases I will import the object into Blender and use the “decimate” modifier on the planes (with an angle of about 20 if you are interested). In the case of the door object it was pretty simple, it is just a door after all, and I didn’t need to optimise it.

Here is what the door looks like in MagicaVoxel:

Notice that the door object is sitting just forward of the enclosing frame and that when exporting the object the center is at the middle bottom plane of that frame. The door is off center because it’s modelled to fit exactly in a doorway that sits exactly in that position within the frame. This saves me a huge amount of time lining everything up when it gets to Unity as the position of the door (or any other object for that matter) is already in the right spot. The problem is that the point of origin for the door is in the wrong spot. It exports a few units behind the door and on the floor! This becomes important when you try and rotate that object (like you would when opening and closing a door) and the pivot point is not where the hinges should be.

To fix this I had to import the .obj file into Blender and reposition the point of origin for the model.

This is what it looks like in Blender when I did this:

To do it I selected the edge that I wanted the door to pivot on when opened.

Then in Edit Mode:
Mesh -> Snap -> Curser to Selected

In Object Mode:
Object -> Transform -> Origin to 3D Curser

So that puts the curser onto the correct position in the middle of that edge where the hinges would be and resets the point of origin (which is where it will pivot when rotated in Unity) to the right spot.

Once we were all imported into Unity and looking good I set up a prefab for the “Doorway” object with the door as a child object. The doorway object has a bunch of colliders to stop the player walking through the walls and a big sphere collider where the door would be to trigger the open / close function when the player walks into it.

This is what the doorway looks like in Unity:

Next I scripted up a few options for opening the door. I’ll post the script at the end of this article but basically there were three options of opening the door that I wanted to test. (Actually I tried it about six ways but whittled it down to the most simple methods – and just as an aside there is an actual “hinge” object type in Unity if you ever need it).

This is how the script looks in the editor:

Notice the slider at the bottom to control how far I want the door to open. It’s really handy to have this when playing in the editor and getting your settings right. If you want to know more about using it see this post

The three tick boxes are for testing the three different ways of opening the door.

Snappy was a quick simple transform of the position from open to closed with no “in betweening”. It looks a bit unnatural as the door magically goes from closed to open but it’s not too bad and most people are pretty used to similar behaviour in video games.

The active line in the code is:
the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);

The next method works more like a door should. In that it swings open and closed the whole way in a steady fashion. But the big problem with this method was that it was OK when the character was going into the doorway and with the swing of the door but when it was time to come back out of the doorway the door was in the way. There was not enough room to trigger the door opening from the other side without being hit by the door as it opened. Plus if the player enters the collider from the wrong trajectory the character gets pushed through a wall by the swinging door which is sub-optimal. I called this method InTheWay!

The active line here is:
the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);

In an effort to combat this I chose to do a hybrid method that opened the door to a point that wouldn’t hit the player and then do the magic transform to get all the way open. I call this one aBitBoth. It looks a little weird too. Like there is an angry fairy pulling the door closed with a snap after the character enters.

Here are all three to compare.

Snappy

In The Way

A Bit of Both

I’m not too sure which one I’m going to use at this stage as the Snappy method works best for now but I like the In The Way method better. I looks more normal and I like that you have to wait just a few milliseconds for the door to swing (adds tension when you are in a hurry to escape a bullet in the back). I could do something like halt the player movement from the rear of the door when it triggers to open from the closed side or maybe play around with the radius of the sphere. Neither solutions seem like great ideas to me right now but something like that will need to be done if I’m going to use that method. Maybe I could just have the door swing both ways and open to the outside when he is behind it but that’s probably a bit weird for a hotel door.

Here is that script that I was testing with:

using UnityEngine;

public class OpenDoor : MonoBehaviour {

    public bool openMe;
    public GameObject the_door;
    public bool snappy;
    public bool inTheWay;
    public bool aBitBoth;
    public Vector3 targetPositionOpen;
    public Vector3 targetPositionClosed;

    [Range(0F, 180F)]
    public float turningOpen;

    void Start ()
    {
        targetPositionClosed = new Vector3(0f, 180f, 0f);
        targetPositionOpen = new Vector3(0f, turningOpen, 0f);
    }

    void Update()
    {

        if (openMe)
        {
            OpenMe();
        }
        else
        {
            CloseMe();
        }

    }

    private void OpenMe()
    {

        if (inTheWay)
        {
            if (the_door.transform.rotation.eulerAngles.y > turningOpen)
            {
                the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);
            }
        }

        if (snappy)
        {
            the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);
        }

        if (aBitBoth)
        {
            if (the_door.transform.rotation.eulerAngles.y > turningOpen)  // 144f
            {
                the_door.transform.Rotate(-Vector3.up * 90 * Time.deltaTime);
            }
            else
            {
                the_door.transform.rotation = Quaternion.Euler(targetPositionOpen);
            }

        }

    }

    private void CloseMe()
    {
        if (inTheWay)
        {
            if (the_door.transform.rotation.eulerAngles.y <= 180)
            {
                the_door.transform.Rotate(Vector3.up * 90 * Time.deltaTime);
            }
        }

        if (snappy)
        {
            the_door.transform.rotation = Quaternion.Euler(targetPositionClosed);
        }

        if (aBitBoth)
        {
            if (the_door.transform.rotation.eulerAngles.y <= turningOpen)  // 144f
            {
                the_door.transform.Rotate(Vector3.up * 90 * Time.deltaTime);
            }
            else
            {
                the_door.transform.rotation = Quaternion.Euler(targetPositionClosed);
            }
        }
    }

        void OnTriggerEnter(Collider col)
    {
        string colName = col.gameObject.name;
        Debug.Log("Triggered OpenDoor!!! : " + colName);

        if (col.gameObject.name == "chr_spy2Paintedv2" || col.gameObject.name == "BadSpy_Package(Clone)") 
        {
            openMe = true;
        }
    }

    void OnTriggerExit(Collider col)
    {
        if (col.gameObject.name == "chr_spy2Paintedv2" || col.gameObject.name == "BadSpy_Package(Clone)") 
        {
            openMe = false;
        }
    }

}

Indie Game Release Click Through and Conversion Rates

Hi Harmony here…

Last Sunday we released our game The Dog Run into the Google Play Store.

This post is a breakdown of the first week release click through rates from this web site and the conversion rates that resulted in an actual download of a game.

Let me say from the outset that without some form of “advertising” or publication campaign a new game on the Google Play Store is never going to be successful.  We found this out the first time around with our game NumBlocks:

NumBlocks is a fun little numbers game that’s a bit like Tetris with numbers that add together. It was our first game with Unity and only a bit more than an experiment in finishing a game that looked good enough to publish.  We weren’t that proud of it and were really just proving our development and release cycle for future games.  It was never publicised and never got downloaded…by anyone.  So if you are not promoting your game… no-one is looking … and no-one will play it.

This time around with The Dog Run we really do want people to play the game and enjoy it. The game is a simple endless runner with a quirky hand drawn style that held many interesting development challenges. More information about the game is available here:

The Dog Run

But what I want to investigate and be transparent about is the way we used this web site and the landing page as a way to interest people into playing the game.

We released the game into the Production Google Play Store on Sunday October 21st.

On the next day at about 8 am New York time we posted on social media channels (we found from research, and validated with our own posts over several months on this site, that this is one of the times of the week that got the most traffic).

We only used Reddit, Facebook and Google+ to promote the release of our game.  We Tweeted and posted to LinkedIn and Tumblr but no-one really follows our feeds on those platforms so I won’t count them.

This is the list of Groups that we hit on social:

Facebook

IGC : Indie Game Creators
Unity 3D Game Developers
Unity 3D Game Developers (different group)
UNITY3D Game Developers
GameDev Show and Test
Game Developers
Indie Game Players & Developers!
INDIE GAMES
Indie Game Promo
Indie Game Development Feedback (IGDF)
Indie Game Chat
Indie Game Promotions

Google+

Unity3d Indie game developers
Unity3D Mobile Developers
Unity 3D Enthusiasts
Unity 3D Developers
Android Apps and Games-Android Mobile Zone
Android Game Developer
Free Mobile Games
Game Developers
Game Developers (different group)
Mobile Game & App Developers
Unity
Unity3d Indie game developers
Unity 3D Developers
Unity3D Mobile Developers

Reddit

/r/Games/
/r/gamedev/
/r/androidapps/
/r/AndroidGaming/
/r/gamernews/
/r/IndieGaming/
/r/androiddev/
/r/gamedesign/
/r/devblogs/
/r/SideProject/
/r/playmygame/
/r/Unity2D/
/r/IndieDev/
/r/indiegames/

So what can we say about this set of groups?  Well they are all Gamer’s Groups. These are “our” people. This is where we go when we need feedback or inspiration or help.  We may not be active in all of them and by no means is this an exhaustive list but after working our way through this lot on a Monday morning there is no energy or time left to look for more groups to join and contribute to.  So this is not a “general public” group nor are they representative of what I think our target audience might be.  But these are gaming enthusiasts and I think more likely to try new games and provide that sort of validating critical and informed feedback that is important for making the game better.  (I love you all!)

So now for the stats….

After seven days since posting these are the figures that hit our website (which normally gets about 20 – 30 visitors a day).  The graph below shows the two weeks previous to release and is indicative of the sort of traffic we get. The blue bar just under the 500 mark is what happens when we do a blog post.  The big orange one is the day after our “social media campaign” (if you could call it that).

Total number of visitors over that week was: 1199

But as you can see a day or two after we posted the traffic dropped straight back to normal. Although the traffic we did get that week was all mostly to look at the landing page of the game.

It is interesting to see where that traffic came from  –  and it’s overwhelmingly Reddit that drives the traffic to our site.  This image below is the stats from the big orange day.

So as you can see even though we posted to heaps of groups in Google+ and Facebook not many users of those platforms were reached.

Out of this massive spike in traffic the number of people who actually clicked on the link to go to the Google Play Store was: 76

This is about 6.5% (rounded up) of our total traffic during that period.  Every day during that week the click through rate was about the same average rate.

Now for the fun part.  Out of those 76 players the number who actually downloaded the game and played it was:  21!

Well that’s a huge improvement over none.

I was very excited by this number.  I’ll type it again in long form…..  Twenty One !

So what I want to drive home with this post is the amount of traffic that you got to drive into your web site to get the sort of volumes that will get your game downloaded.

Let’s break it down into simple numbers……  Out of 1200 people only 75 looked at the game and out of that number only 21 downloaded it.  That’s 1.75% of the traffic to my landing page downloaded the game. That’s the truth of it and remember that these are “our peeps” not the general public so I couldn’t even say that this is indicative of the way the real world works.  But it sure is interesting and in a few months after I’ve spent some time marketing this game to real people (not just the gaming community) I’ll do another post and see if the stats still hold.

Harmony out!

P.S. If you want a friendly copy of all those social media links email me at zuluonezero.z10@gmail.com and I’ll forward them back. (Maybe on a later post – if there is enough interest – I’ll  put them online). Zulu.