What I learned from “Don’t Touch My Planet!”

Every new project is a good learning experience, especially if you are a game designer buffing up your programming skills. I will share with you what I have learned from building “Don’t Touch My Planet!” on Unity 3D. My Planet is an experimental twist on tower defense games, you can grab it from here.

Don't Touch My Planet!

Technical Stuff

 

Upgrades

 

Upgrades are a great way to make games more engaging, tactical and long lasting. They emphasize the sense of progression and give you a nice way to layer and filter your game experience. But for small games upgrades can be costly. They require save system that will track players progress in every item that can be upgraded. This increases task difficulty quite a bit. For game developers who have not invested in saving system before, this might seem scary.

The problem with saving many items is that you either have to directly save too many variables, or you have to write a system that can save custom classes and load them. You might also have to write code that will synch these saves between different cloud solutions on different platforms. The way I navigated around these issues is by basing all item progression on only one variable: items level! So this way you only have to save one variable per item.

Every stat of the item can be recreated from just the items level and there are many ways to do that. For example for players shield we needed simple liner progression so we have two variables.

 

Shield variables

One is starting health, another is how much health should be added each level. So with simple function shown bellow we can learn shields health for any level.

1
2
3
4
5
public int GetHealthForLevel(int _level)
{
    return statsBase.health+statsIncreasePerLevel.health*_level;'
    //base health + increase * item level 
}
public int GetHealthForLevel(int _level)
{
	return statsBase.health+statsIncreasePerLevel.health*_level;'
	//base health + increase * item level 
}

Any time you need to learn base health for an item, you can call the function “GetHealthForLevel()” with current level passed as an argument. For example at the start of the game we could set items currentHealth variable to baseHealth. So we start with full HP. We can do it like this:

1
currentHealth = GetHealthForLevel(SaveManager.shieldLevel);
currentHealth = GetHealthForLevel(SaveManager.shieldLevel);

You could also use arrays to store what value an item should have on each level

1
2
3
4
5
6
int[] healthPerLevel;
 
public int GetHealthForLevel(int _level)
{
    return healthPerLevel[_level];
}
int[] healthPerLevel;

public int GetHealthForLevel(int _level)
{
	return healthPerLevel[_level];
}

or even better use curves to define balance  (more on this below). Basically as long as you don’t have randomized stat increase on levels this should work for you. The scenario where this would not work is for example: in DnD your character rolls a dice each level up to see how much health it should give you, with min/max health increases. But this is kind of a dick move so 😀

Time based upgrades

 

Another cool feature popular on mobile games is time based upgrades. Basically when you upgrade something you have to wait X minutes before upgrade is ready. Trick is you need to save time, so that when player shuts down your game and returns later he should receive all the upgrades that should have been ready by that time. So tracking only time during playtime is not enough, as that data will be lost when the game is closed.

To implement this feature, you need to make an important decision first. Do you rely on device clock to check against time or do you use your server clock for this.

Device clock is easy to access and works offline, but player can cheat by changing the actual time on his device. Server clock is impossible to cheat but requires active internet connection and you also need to have a server. Some games allow you to play offline, but only give you access to time based mechanics if you are online.

For “Don’t Touch My Planet!” I went with offline approach. I didn’t want to force internet connection on purely offline game. Though for online or highly competitive games you will need to use server time.

You can implement timed upgrades using DateTime and TimeSpan constructs. You will need to add “using System;” at the top of your script to use this functions.

DateTime  – Represents an instant in time, typically expressed as a date and time of day.

TimeSpan – Represents a time interval.

During upgrade we must get current time from the device system clock and save it as a string. We can get it by using “DateTime.UtcNow.ToString()”. UtcNow will give you time that is independent of the time zone, so you don’t have to worry about players going back in time when they fly to different countries.  Your save code could look like this:

1
PlayerPrefs.SetString("shieldUpgradeTimer", DateTime.UtcNow.ToString());
PlayerPrefs.SetString("shieldUpgradeTimer", DateTime.UtcNow.ToString());

PlayerPrefs” is the easiest saving option in Unity.

Next time when you need to check if an item has been upgraded, you need to load saved time string and process it:

1
2
3
4
5
6
7
8
9
//load saved time string
string time = PlayerPrefs.GetString("shieldUpgradeTimer");
//variable to store saved time
DateTime savedTime;
//try parse method will check if string is correct and load it into datetime Variable, it will return false if parsing failed
if (DateTime.TryParse(time, out savedTime) == false)
{
    //saved time is corrupted, implement failsafe
}
//load saved time string
string time = PlayerPrefs.GetString("shieldUpgradeTimer");
//variable to store saved time
DateTime savedTime;
//try parse method will check if string is correct and load it into datetime Variable, it will return false if parsing failed
if (DateTime.TryParse(time, out savedTime) == false)
{
	//saved time is corrupted, implement failsafe
}

Then we need to check how many seconds have passed since we ordered an upgrade:

1
2
3
4
5
6
7
8
9
10
//lets get current time
DateTime timeNow = DateTime.UtcNow;
//time span can help us to calculate how much time has passed after an upgrade has started
TimeSpan timePassed;
//substract saved time from current time to get interval inbetween
timePassed = timeNow.Subtract (savedTime);
if (timePassed.TotalSeconds < 0)
{
    //player changed his clock to previous date, he is now BACK IN THE PAST!!! implement the failsafe
}
//lets get current time
DateTime timeNow = DateTime.UtcNow;
//time span can help us to calculate how much time has passed after an upgrade has started
TimeSpan timePassed;
//substract saved time from current time to get interval inbetween
timePassed = timeNow.Subtract (savedTime);
if (timePassed.TotalSeconds < 0)
{
	//player changed his clock to previous date, he is now BACK IN THE PAST!!! implement the failsafe
}

After that lets check if enough time has passed to warrant an upgrade

1
2
3
4
5
6
//we need variable to know how many seconds are required to upgrade an item
double secondsNeededToUpgradeItem = 300;
if (timePassed.TotalSeconds >= secondsNeededToUpgradeItem)
{
    //Enough time has passed, upgrade an item 
}
//we need variable to know how many seconds are required to upgrade an item
double secondsNeededToUpgradeItem = 300;
if (timePassed.TotalSeconds >= secondsNeededToUpgradeItem)
{
	//Enough time has passed, upgrade an item 
}

BOOM HEADSHOT! You can now laugh from the shadows as players stare at the timer and wait impatiently for upgrades to finish. Speaking of timer, here is a bonus code for you to display the timer.

1
2
3
4
//lets check how many seconds are left until upgrade is ready
TimeSpan timeLeft = TimeSpan.FromSeconds(secondsNeededToUpgradeItem-timePassed.TotalSeconds) ;
//We can use string format to convert timespan into a time string 
string timeToDisplay = string.Format("{0:00}:{1:00}:{2:00}",  timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds);
//lets check how many seconds are left until upgrade is ready
TimeSpan timeLeft = TimeSpan.FromSeconds(secondsNeededToUpgradeItem-timePassed.TotalSeconds) ;
//We can use string format to convert timespan into a time string 
string timeToDisplay = string.Format("{0:00}:{1:00}:{2:00}",  timeLeft.Hours, timeLeft.Minutes, timeLeft.Seconds);

Don’t forget that you will need to add “using System;” at the top of your script to use DateTime and TimeSpan functions.

Animation curves for balance

 

To get most out of the only one variable based upgrade system, we can use Unity’s animation curves to have more control over how item stats will change over levels. Curves represent value over time, looking at image below should give you an idea of what the AnimationCurves are.

Curve

You can use them to visually see how stat will change over levels. Vertical coordinate would be the stat value, horizontal coordinate would be the level. I used this to control enemy stats. The value of the curve on certain level directly represents stat value.

You can define Animation curve as public variable:

1
public AnimationCurve Rocket_L_Health;
public AnimationCurve Rocket_L_Health;

curveVar
The curve will represent how stat will increase over certain amount of levels. For example this one curve shows how stat will increase every 10 levels. after 10 levels we need to repeat the curve, so that it can show us the stat values for the next ten levels. We do this by looping the curve. but if we let unity do that we get something like this:

curves2

Not very useful. On wave 11, when we repeat the curve stat would be back to the value of 0. What we are looking for is looping like this:

curvesLoopSo the form of the curve is repeated, but new curve starts on the value the previous curve has ended. And that’s exactly how we accomplish this. When we repeat curve, we add last value of the previous curve to it.

We can use this to have controlled progression of the items value over levels, and we can do that by one simple function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// this function returns item value on provided level, it needs 3 variables
// _curve is AnimationCurve that has Item's balance on it 
//_level is current level of the item 
//_stepping is basically, how many levels should we calculate from one curve, before repeating it
public float GetCurveValueForLevel(AnimationCurve _curve, int _level, int _stepping)
{
    //we calculate how many times has the curve repeated itself
    //for example if one curve represents 10 levels and 
    //current level is 25, stepping multiplier is 2
    int _steppingMP = Mathf.FloorToInt(_level/_stepping);
    //now we need to determine on which step we are in current curve
    //so if curve represents 10 levels and current level is 25
    //we need value of 5, that is where we are on current curve(20 to 30)
    //20 just means, we have looped through our curve twice
    //check image above to understand this 
    int _currentStep = _level - _steppingMP*_stepping;
    //the curves give us value over time. By default time length of the curve is 1 second
    //so we need to determine what percent of 1 second _currentStep represents
    //first we get what percent of stepping the currentStep is
    float percent = _currentStep*100f/_stepping;
    //now we get x Percent of 1 second
    float _time = 1f*percent/100f;
    //now we get what value the curve has on given time
        //then we add stepping multiplier, to create looping like on image above
        //basically the last value of the curve multiplied by the number of times curve was repeated
        float _value = _curve.Evaluate(1f)*_steppingMP + _curve.Evaluate(_time); 
        //because it's easier to edit curve at very small values, lets multiply them so we get normal value numbers 
        int _multiplier = 100; 
        //return value 
        return _value*_multiplier;
}
// this function returns item value on provided level, it needs 3 variables
// _curve is AnimationCurve that has Item's balance on it 
//_level is current level of the item 
//_stepping is basically, how many levels should we calculate from one curve, before repeating it
public float GetCurveValueForLevel(AnimationCurve _curve, int _level, int _stepping)
{
	//we calculate how many times has the curve repeated itself
	//for example if one curve represents 10 levels and 
	//current level is 25, stepping multiplier is 2
	int _steppingMP = Mathf.FloorToInt(_level/_stepping);
	//now we need to determine on which step we are in current curve
	//so if curve represents 10 levels and current level is 25
	//we need value of 5, that is where we are on current curve(20 to 30)
	//20 just means, we have looped through our curve twice
	//check image above to understand this 
	int _currentStep = _level - _steppingMP*_stepping;
	//the curves give us value over time. By default time length of the curve is 1 second
	//so we need to determine what percent of 1 second _currentStep represents
	//first we get what percent of stepping the currentStep is
	float percent = _currentStep*100f/_stepping;
	//now we get x Percent of 1 second
	float _time = 1f*percent/100f;
	//now we get what value the curve has on given time
        //then we add stepping multiplier, to create looping like on image above
        //basically the last value of the curve multiplied by the number of times curve was repeated
        float _value = _curve.Evaluate(1f)*_steppingMP + _curve.Evaluate(_time); 
        //because it's easier to edit curve at very small values, lets multiply them so we get normal value numbers 
        int _multiplier = 100; 
        //return value 
        return _value*_multiplier;
}

This might seem complicated at first, but it’s really simple. We use the curve to represent the value of a stat over certain amount of levels, which I called stepping. If our level is larger than stepping, we repeat the curve but now with higher values. Each time we finish the curve, steppingMP is increased.

But we always evaluate curve withing current stepping. So we determine where we are in current curve loop. Then we translate our position into curves time variable. After which we get what is the value at current time. It is really worthwhile thing to understand. Because if you have your balance with visually representable curves, you can overlay different curves on top of each other and you can pretty much visually create perfect balance.

If you have cooler way to track your balance, please let me know ^^

Non Technical

 

 

Plugins

 

Whether to write all your features yourself or speed up development with 3rd party tools is a topic of great debate. On one hand it is easier to use and build upon your own tools, on other hand reinventing the wheel.. well the expression is self explanatory. But while there are pretty standard and safe external solutions like physics libraries or game engines. Sometimes you have to deal with more questionable products like for example plugins on unity asset store. These are often developed by one person who might see his submissions as a hobby and side income, thus they might not have the dedication to deliver quality that a company fully dependent on their products success would have.

You will have to analyze this situations and weight several factors. Is the feature you have generic or very specific and unique? If you are building a revolutionary physics based puzzle game, reinventing the wheel might just be the best thing you can do as you will most likely need more control than standard solutions can give you.

But if standard thing is fine with you, then you need to think really hard if spending your own time to develop this feature is really worth it when there are perfectly usable solutions out there. Chances are you are not doing anything revolutionary with your hud (please don’t), so it might be a safe bet that your valuable time is better spent making better gameplay than slaving over annoying and tiresome task like making user interface that can work on all platforms and all resolutions. ( I spent less than 10 minutes doing that with Ngui.)

Another good reason to use plugins is that you might not want to face every possible challenge with your first game. Even if you want to fully rely on your own tech, you might want to get to that point step by step. Remove extra noise like hud or  touch controls from your first game. Build solid gameplay mechanics and on your second game you can focus replacing external tools with your own. Having a long term vision about tech of your company really helps.

Now I’ll get to more specific cases on this subject by giving you a small review of the plugins I used.

NGUI – this plugin is so amazing that Unity actually hired the guy behind it and in update 4.6 you will see this replacing Unity’s existing GUI system. If you can’t wait for 4.6, definitely buy this plugin.

Master Audio – I love it. I picked this up for 10$ on sale and I got pretty powerful, simple to use audio system. It has events for default behaviors like disabled/enabled and you can write custom events. You can easily create random sound groups, music track mixing etc.

IOS Native – This allowed me to do everything I wanted to do on IOS, like leaderboards, InApp, iCloud. But I would not rely on third party plugins when it comes to porting to mobile devices. You should use plugins like this to let you publish your first few games, but eventually you will need to be able to use native SDKs and commands. Mobile platforms are tricky, they update often and in way that might break your functionality and when that happens, your amazing google skills won’t always be enough to effectively resolve the issue. So definitively plan to invest in in-depth knowledge of native SDKs and don’t put off this task for too long.

Official Facebook SDK – It works, kind of. But it really does not fill like solid solution and makes you worry about beta status. In xCode it gave me a lot of minor warnings when I built my project. They didn’t break anything but it just does not feel “clean” and stable.

New Services We Tested

There are tons of services built around games, especially mobile games. Some of them let you use common functionality like displaying ads or tracking your games performance. Some offer bizarre new ways to allow your players to interact with your app in innovative but often questionable forms. In this section I will review the services we tested with current game.

I serve ads in “Don’t Touch My Planet!” and I used Chartboost to do so. I don’t have enough data yet to see how well it performs income-wise but I have good feedback from people who use Chartboost. I used unity plugin to serve ads and it was very easy to implement, worked within few minutes. Make sure to use custom locations to get better feedback from analytics.

To track analytics I used GameAnalytics. It’s a great start and you should definitely consider implementing it if you have not used analytics in your games before. With just few steps you will be able to track all the important KPIs without writing a single line of code. It tracks all the retention, user and session length data you might need.

Tracking custom events requires just one line of code. I would recommend that you at least track every step of the tutorial and whether or not players have interacted with all your features to see if players are understanding your game. For example send event first time player opens a store.

A lot of people drop games on their tutorials, so compare how many hits you have on each tutorial step and you can see where you are loosing your first time users. Fix those places in your next update.

You can also use game analytics to generate heat maps if your game is level based. Send custom events when snipers kills a target for example to determine what map points are being exploited by them. You can then preview heat map directly in unity, it will overlay your scene. This is just super awesome.

Well I guess that’s it 😀  I hope you found this useful and reach out if want to ask anything.

Cheers!

 

Jumping and stuff..

Soooo.. blog post time!

We had playtest in Gamefounders office sometime in near past, I edited a cool video. I know I have a crappy camera, but directing and editing genius make up for it 😀

Yeah, we don’t make easy games that’s for sure 😀 It was great diabolical pleasure to watch people suffer with levels we made, but they kept at it until they mastered the game and had happy faces of triumph when well deserved victory came at last, so we must be doing at least something right 😀

There should be a new playtesting day this week, I’ll try to make a post about it faster this time.

The Gamefounders program is going awesome. We had time to polish and build up on our games, we have met cool new mentors, even got a free Blackberry (Don ^^). Meo managed to get lost couple more times, so all in all it’s going great.

I’ll be posting more about our new games soon, so be sure to keep checking this blog, It’s going to get awesome, I promise 😀

P1080031  P1080268 P1080285
And as mentioned in a video, you can send mail to info@jumporfall.com and we’ll send you free games to test and enjoy.

Cheers!

Sandro.

 

 

Tallinn and Game Night

In case you missed our facebook update we are now in Tallinn, Estonia! We’ve been here for two weeks already in the amazing Gamefounders program. In this short time Jump or Fall has met many industry gurus and gained useful insights from their training. We have even made a close escape from being renamed to “Jump and Fall” 😀

Somewhere over Europe From Riga to Tallinn

Bombardier

Airpot

I didn’t get a chance to see much of Estonia yet, only a small part of Tallinn and it has left an amazing impression on me. There are two kinds of stories cities can tell that are most interesting to me. One is a story of life, the kind of flow and vibe people go through every day of their lives. Their hopes and dreams, the binding mark of culture and society and struggle to stay within it or break free from it. This I’ll admit is still a mystery to me, Estonians seem very reserved and quiet people. So far I have learned more of Brazil (cheers :D) than Estonia in that regard.

The other kind of story city can tell is ground deep within the stone, concrete, earth and trees that makes up it’s body. It is the mood and the atmosphere of the place and it is best seen at night when the streets are the most quiet. This story I’m getting to know a little better and I don’t think it gets quieter anywhere else compared to Tallinn. Streets are very wide, buildings far apart so there is a sense of vast space everywhere, in contrast to this, the busiest of the streets never have more than a handful of people walking down them at one time. At nights the emptiness can get eerie.

Meo and I often stay very late in the office, sometimes we miss the last public transport and we walk back home. Even though it is very easy to navigate the city, our RPG roots take hold and we often find ourselves exploring the wrong turn or two. Old town in the night feels like a medieval adventure or survival horror. Walls around old town with mix of old buildings and neon bright night clubs puts you into a Deus Ex mood. Some areas with colorful wooden houses feel like you have wandered into a toy town, but there are places where it gets so quiet it becomes disturbing. You feel like you have been dropped into a video game prototype level that only has art and few ambient sounds added to it.

Elk Soup

Streets Grey OldTown

The city was designed by open world exploration mastermind, most of the houses are three or four story high, but there always is an interesting tall structure in the view. You will never run out of fascinating focal points to grab your attention and lead you to it. Every bus stop has the city map so you can always get back on track if you got yourself lost.

The Gamefounders program is INTENSE, but in a good way. We meet a lot of interesting people, who have worked on epic titles (Final Fantasy, Legacy of Kain, Heavy Rain) and they have amazing amount of experience to share. From the day one you get the motivation to really focus and define your goals, then find clear ways to reach them.

Seminar

On friday night we had a little booth(?) at the event called “Game Night”, to be honest I never properly understood what the event was all about. But it was held in a big ass movie theater, where people played “Injustice” on big screen (yeah, the giant one you watch movies on). There were PlayStation 4 stands with very boring game selection and some very cool old school games you could play on custom controllers. There was even one arcade like controller mounted on female mannequin that projected Chip ‘n Dale Rescue Rangers (video game) on a t-shirt.

JumporfallPS4 Mario Controller

Somewhere among all this madness, Jump or Fall and other teams from Gamefounders program had a chance to show people our (their) indie games! It was awesome, even with huge competition from Nes, Gamecube, PS4, and Big Screen Injustice game a lot of people dropped by our stand and played our games. The feedback was amazing, people would stop and check out each of our games and give us feedback. It was great feeling to see them having fun playing games we have worked on.

Oh and we found good places to buy beer, our faces should show you how we feel about that.

^___^ ^___^ ^___^

 

 

 

First Game Jam in Tbilisi, Georgia

Yesterday and the day before that, or more specifically on February 22-23, 2014, from 10am to 9pm for someone who likes specificity, there was a first ever Game Jam held in Georgia. The attendance, team participation and enthusiasm went so high beyond the expectations that they could kiss the moons! (if you don’t know where this expression is from, you’ve missed one hell of a game). There were three speakers from Jump or Fall on this event and one of us was also a part of jury, which judged the games with a tear in its eye and pride in its heart.

 

First Game Jam in Georgia

First Game Jam in Georgia

 

Since this was the first Jam, we thought that if up to 10 teams would show up, that’d be a good start. To our great surprise, we had 24 teams in the end! Not only that, the ages ranged from 14 to 50+. I’ll be honest, I had no idea that so many people in Georgia are actually into game dev and it did take me by surprise despite my high resistance to the element of it (surprise).

 

1939612_261798527319279_1690145858_o

 

The event was very smooth and went just as planned. The only unforeseen thing was the amount of people present, which only boosted everybody’s spirits and made the entire thing more fun. The event consisted of various speakers about different topics, such as how to optimize assets, game industry and how to approach it, current game standards, tips to game dev teams, etc. There were breaks in between with coffee, tea and some cookies (who doesn’t love free cookies?) and at some point there was a full food menu available. Yeah, the post is about Game Jam and I’m elaborating on food, what of it? I love food, I often think about food and therefore I write about it when it’s relevant. Now aside from just food, the organizers promised us a cake at the end. Of course that did seem dodgy as hell after Portal but we went through with the Jam anyway and what do you know, the cake was not a lie!

 

 1618243_261848493980949_372860735_o

 

Ok I’m done about food. Besides speaker presentations, there was also a fun quiz-like game where we asked the audience gaming related questions and the participation was pretty fierce to say the least. I also secretly enjoyed the feeling when no one knew the answer because the questions were created by me and Sandro and in that moment we felt smarter than everybody else… people need that kind of moments, even if they’re illusory ones.

 

I know it! pick me! I know!!

this is the very end of Day 1, that’s why the attendance is not in its fullest

 

Needless to say, the event had a lot of press coverage and the media did an awesome job documenting these two days. Later, I’ll post a presentation with English subtitles so you guys can understand it (and also be bewildered by how Georgian sounds). All in all, the Game Jam was a blast, engaged tons of people and spewed fun in all directions. I’ll try to provide the top three winner game footage when I have all the materials. As of now, everybody’s asleep after the hard Jam and the pictures and videos are yet to be uploaded (and I didn’t wanna wait till then so I write this blog post anyway). Another Jam is being planned in May although it’ll be awesome if it’s moved to June since Jump or Fall will still be in Estonia in that time. ეს ერთი და სხვა მრავალი! (google translate can hint on this one)

 

Yours truly,

~ Sanders