BLACKISH DEV BLOG Support
 

 

Unity: How to create an array with values in it

C#: public int[] val = new int[3] {1, 2, 3};
JS: var val : int[] = [1, 2, 3];

Leave a comment

Greatest App Ever – Rejected

In early 2009 the App Store hype was at its max, everyone loved reading stories of one-man-companies getting filthy rich with ridiculous apps. Well, I was getting a bit sick of it to be honest… So I set out to end it all by creating the ultimate iPhone app.

I stripped away piece after piece until I arrived at the pure and beautiful core – the heart of it, if you will – and created the ultimate App Store app to rule all other apps. Simple, yet deep. Fast to grasp, yet always new.

Unfortunately the Apple App Store review team didn’t recognize the artistic value, let alone the cultural importance of this app and rejected it for offering “no value to the user”.

Money Generator
An app that does nothing but display
how much money it has generated.
PS: There was also going to be a free trial version:
2 Comments

Unity: Calling C# functions from a JS script

In short: the C# script has to be compiled before the JS script for this to work. To achieve this you have to move the C# script into one of the following directories: Plugins, Standard Assets or Pro Standard Assets.

It also works the other way around – if you want to call JS from C#, move the JS into one of the folders.

It does not work both ways at once however.

More info about script compilation order can be found in the Unity docs here…

Leave a comment

GameDev Audio Workflow

This is my current workflow for recording, mixing and exporting audio for use in my games. (Currently recording dialogue…) I’m very interested in your approach, so leave a comment, tweet to @col000r or send me mail if you want to share your workflow!

Apple Logic Express 8:

This is where I record and mix all the Audio. (Or at least try to, because IMHO Logic is a mess)

To make my life easier I usually cut all the dialog into separate clips and name them with the first few words of the first sentence in the clip, split everything into separate tracks for separate characters and use color-coding to mark the clips I like best if there are multiple takes. (Rarely do I use comps, I just don’t find them very helpful…)

I currently keep all the dialogue in one big file (so I can tweak the sound of individual characters all at once). It’s not possible to batch-bounce files from markers, so I just add a region marker for each mission, select that range and bounce the whole mission to a WAV.

Adobe Audition CS 5.5:

That WAV goes into a multitrack session in Audition where I split all the dialogue into small pieces by creating named marker regions and batch-exporting them to files. (They need to be short because they’re going to be loaded at runtime and any file larger than a few KB will cause a short pause on iOS devices…)

I add markers to a multitrack session and not directly to the WAV because there is no way to copy/paste markers, and if you copy/paste audio from one file to another it clears the markers. Thus this is the only way to preserve markers when you want to re-export the files from a new bounce without having to set up everything anew.

A short how to:

  • Move the playhead to any position
  • Press Shift+Cmd+M to create a region marker
  • Adjust the in and out points of the region, open the Markers window and rename the marker (we’ll use the name as the filename later on)
  • When all markers are done, do a Multitrack > Mixdown to new File
  • Select all the markers in the Markers window and click the “Export audio of selected range markers to separate files” button.
  • Done!

Unity 3.4:

Back in Unity I’ll set the audio-files to mono 96 kbs Compressed StreamFromDisk – that’s the best setting I’ve come up with for the iOS version of the game. I wrote an Editor-script that lets me batch-change the audio format of all selected files to this, to save some time. I haven’t looked into the best solution for the desktop version yet, but the base files are all 44.1khz, 16 bit stereo WAVs, so there’s room for improvement…

Then I’ll drop everything into a custom editor window (as blogged about before here), copy/paste the dialog from the script, call the right pieces at the right time from script and finally in the end it looks like this:

(If you want to see and hear it: http://beta.blackish.at)

2 Comments

Monetization Horrors

Monetization in progress… Oh the horrible ideas that come from being able to sell stuff via in-app purchases…

Wacom Bamboo Paper: A notebook to draw in. Nice! But if you want more than one notebook you have to pay. This feels so wrong… You’re not paying for new functionality, you’re paying for more of the same and it feels just plain wrong. It’s a bit as if Adobe started charging for colored pixels : “Your blue digital-ink is low, buy 1000 milipixels for $10″… but speaking of Adobe:
Adobe Ideas. It really is a nice and clean app. $5.99, huh, well, okay… Peanuts compared to the huge pile of money I threw at them for the Creative Suite, right? So what have we got here? Pencil, eraser, colors, buy layers… BUY layers?! What the hell! What did I pay $5.99 for? Now I need to pay another $0.99 to use layers? Screw this!

OffMaps 2: The first OffMaps cost $4 and would let you download map-data from the OpenStreetMap project to navigate while offline (on vacation, etc.). You would just select any area, choose how many zoom-levels you wanted to download and go: download! Easy to use, worked well. But then the greed set in and they built OffMaps 2 where you pay $0.99 to find out that the app comes with 2 download tokens that let you download data for only 2 cities and then you need to pay for more tokens. Oh baby, now I’m being properly monetized! I picture suitcase-carrying yuppies triumphantly shaking hands behind a mirrored glass wall while the test-subject eyes the buy button…

I could list many more examples…I’m not saying all this it doesn’t work, I’m just saying it doesn’t feel right. If you care more about short-term income and less about if your customers feel cheated or mocked, go ahead. But your customers will remember. Or maybe you’re lucky in this 5-min-attention-span market and they won’t. I’m just noting that if your expectations are built up and then you hit pay-wall after pay-wall before you can get to the expected experience, it’s not a good feeling. And no, no one reads the description text before getting a free or cheap app, they look at the screenshots – *bam*, expectations created – download – disappointment.

So when do in-app-purchases feel right?
A few criteria:
  • The app has to deliver a satisfying experience by itself. An app that is obviously crippled without purchasable add-ons is no satisfying experience.
  • Don’t shove in-app purchases in my face from the get-go. Let me breathe and experience the app. If I want more, I’ll check if there’s more.
  • Don’t charge for something that is obviously just a simple change in code (like more notebooks). Yes, it could work, it could even sell very well, but I’ll feel like you’re mocking me and I’m not going to buy it out of spite.
  • Be clear about what’s included and make it very clear from the get go that there is additional content that can be purchased.
  • Don’t tell me you have Downloadable Content (DLC) planned from the start. It’s like saying that you’re planning to charge me over and over and over again to get the full experience. (Assassins Creed 2 had a few chapters in the story arc reserved for DLC – WTF?! I paid EUR 60,- for this and then there’s holes in it?) Rather say something like this: “If a lot of people are interested, we’ll think about developing more content in the form of expansion packs. Those will be available at low cost and if it sells well, we might even give some away for free!” – This feels nice, doesn’t it?
  • Naming the additional content “expansions” or “expansion packs” also feels nice, it sounds like good stuff, it sounds like the old days. “DLC – Downloadable Content” on the other hand is sounding more and more like corporate talk. When I hear DLC I think of corporate manager-types with dollar-signs in their eyes who use the word “monetizing” in every second sentence…
This is not a guide on how to become rich with in-app purchases, these are my very subjective feelings when encountering them in the wild.
6 Comments

The trouble with Angles

The problem is this:

Both calculations give you the same result!

float a = Vector2.Angle(Vector2.up, new Vector2(5f, 2f)); //a = 68.19859
float b = Vector2.Angle(Vector2.up, new Vector2(-5f, 2f)); //b = 68.19859

So how can you get the angle of a vector between 0 and 360 degrees?

double radians = Mathf.Atan2((y2-y1), (x2-x1));
double degrees = radians * 180f / Mathf.PI;
if(degrees < 0) degrees += 360; // degrees are now between 0 and 360

float angle = (float) degrees; //cast to float if you need to

Just use the correct orientation for (x1, y1) and you’re good…

    Leave a comment

    Life is hard, but so am I

    5 years ago I started this blog with a Dresden Dolls quote. Believe me, it was way funnier back then…

    The last months weren’t easy. I guess brain surgery is never much fun, but being self-employed and the father of a 1-year old kid… well, let’s just say that quite a few things were riding on my survival…

    With a little less careful planning and a little less luck this could have ended my “career” as an independent developer quite abruptly.

    But it seems I made it through and so I’m finally back at work on my next game now.

    3 Comments

    Behind the scenes: New Orbit Story Tools

    I’ve put quite a bit of thought into making the tools for the story-part of NEW ORBIT as reusable and practical as possible.

    So here’s how Story, Subtitles, Voiceovers and Character Portraits play together:

    I have a generic class called OnScreenTextController that takes a string, fades it in, displays it for a certain amount of time and fades it out again. In NEW ORBIT I use two classes that are based on it: SubtitleController and CenterScreenGUI – one displays the subtitles and character portraits, the other one shows the current objective in the center of the screen.

    Both are being fed with LocalizationDBItems from the LocalizationDB. (basically just an object that holds an array of LocalizationDBItems) A LocalizationDBItem contains the actual text, the location of the voiceover-soundfile, the ID of the character who’s speaking and the duration.

    The story itself is driven by a Mission-script that knows when to display something and when to wait for certain events to happen. The Mission-script only knows the IDs of the messages and works with the durations it retrieves from the LocalizationDBItems, so I can simply load a different LocalizationDB to switch to a different language and all the timing will adjust automatically.

    I’ve created an Editor-window where I can manage all the text and audio in the LocalizationDB. If I drag in a new voiceover-file it automatically writes in the path and the duration. But if there’s more text in the file than fits into the subtitles-bar I have to manually split it into multiple entries and divide the time.

    Leave a comment

    NEW ORBIT

    Let me introduce my next game: NEW ORBIT

    It’s an episodic space action adventure (or whatever) based on realistic gravity simulation.

    Try the beginning of the game right away on http://beta.blackish.at

    Together with the beta I have launched an experiment: The BLACKISH Beta List. Join to be kept up to date on the development and to receive exclusive behind the scenes material on a semi-regular basis.

    Leave a comment

    Unity Webplayer: crossdomain.xml

    In preparing for the deployment of the very first beta of the next game as a webplayer, I’ve run into a few troubles with webplayer security policies, so here’s how to do it right so it will work in the Editor and in the webplayer:

    In Edit>Project Settings>Editor enter the location where your final webplayer file will be deployed.
    Create a crossdomain.xml file as described here in the docs
    (Now comes the part where I went wrong) The unity docs only give the following example:
    <?xml version="1.0"?>
    <cross-domain-policy>
    <allow-access-from domain="*"/>
    </cross-domain-policy>

    Now this allows access from any domain, what if you want to restrict it? My mistake was to include http:// with the domain, here’s an example that works:
    <?xml version="1.0"?>
    <cross-domain-policy>
    <allow-access-from domain="beta.blackish.at"/>
    <allow-access-from domain="*.blackish-games.com"/>
    </cross-domain-policy>

    The crossdomain.xml file has to be placed at the root of your server and I haven’t found a way to access a subdomain yet. If you know how to do that, please let me know!
    Leave a comment