BLACKISH DEV BLOG Support
 

 

How to create nice DMG Disk Images for Distribution

Here’s my findings on how to create those nice-looking DMGs that people distribute their software with…

  • Create a new Disk Image with Disk Utility (Give it a good name, Make the size large enough – we’ll shrink it later, Format: Mac OS X Journaled should be fine, no encryption, single partition, read/write disk image)
  • Make a folder on the new volume and copy the background image into it
  • set up the background image + icons, etc. (Cmd + J)
  • hide the folder by doing this in the terminal: /Developer/Tools/SetFile -a V /Volumes/your_volume/folder_to_hide (big V hides it, small v makes it visible again)
  • If you want a shortcut to the Applications folder in there, simply drag it in there with alt+cmd pressed (this creates an alias)
  • Make sure to empty the trash if you deleted or overwrote something on the new volume (you wouldn’t wanna ship items in the trash with your DMG…)
  • drag the dmg into the bottom left sidebar in Disk Utility, right-click and choose “Convert“. Image Format: compressed, Encryption: none

Your disk image is now as small as it can be and set to read-only!
Bonus: You might want to make your dmg internet-enabled – this only means that if it’s downloaded from the web it will be unpacked into a folder automatically… (use hdiutil for this)
Want to see the result in action? Download the free trial of our curling game!
Leave a comment

Unity: Windowed, Fixed-size OS X Apps

I want to build a desktop version of an iPhone game… It doesn’t look very well in fullscreen mode because the GUI simply wasn’t built with fullscreen in mind. So…

  • Edit > Project Settings > Player
  • Set Default Screen Width and Height to 320 and 480.
  • Set Display Resolution Dialog to Disabled
  • Set Default is Full Screen to Off
If I build the application like this it will pop up in windowed mode and in the right size. BUT I can still go to the menu and do Window > Full Screen (or press Cmd+F) and break it! Damn… And to make it worse, if you swatch back out of fullscreen mode it doesn’t go back to the default resolution I set in unity, instead it maximizes the window to the entire screen…
Luckily ToreTank pointed me to this thread on the unity-forum that holds the solution:
  • Build the App
  • Right-click on the App in the Finder and choose Show Package Contents
  • Navigate to Contents > Resources and open MainMenu.nib in Interface Builder
  • Select Window > Full Screen from the small floating representation of the menu und hit Delete (If it’s not open already, double-click MainMenu in the Interface Builder Document Window)
And while you’re there you might also want to add your copyright to the About Box…
Leave a comment

Unity: Making the Switch from JS to C# (Part 2)

3.a) Functions

Basic functions are simple enough in Javascript, but might seem weird in C# at first. You just need remember this: [scope] [return type] [FunctionName] (varType varName).
JS
function WriteSomething (str : String) {
print(str);
}

C#

public void WriteSomething (string str) { //"public" means it can be accessed from everywhere (scope), "void" is the return type (void means it doesn't return a value)
Debug.Log(str);
}

3.b) Return

In Javascript you just do it, in C# you need to think ahead and put the return type in the declaration of the function…

JS

function ReturnSomething () {
return "Something";
}

C#

public string ReturnSomething () { // In C# you have to define the type of the value that will be returned - in this case it will return a "string"
return "Something";
}

3.c) Yielding

In Javascript yielding is easy… Just use yield. In C# you have to set the return type to IEnumerator if you want to yield inside a function. (This should also make you understand why you can’t yield and return inside one and the same function…)
JS
function Start () {
yield new WaitForSeconds(2.0);
yield DoIt();
print("Done!");
}

function DoIt() {
print("Doing it...");
yield new WaitForSeconds(0.5);
print("Almost done doing it...");
}

//Output:
//Doing it...
//Almost done doing it...
//Done!

C#

IEnumerator Start() { //if you want to yield inside start you have to change "void" to "IEnumerator"
yield return new WaitForSeconds(2f); //notice the f after the 2! - float
yield return StartCoroutine(DoIt()); //Note: without the "yield return" it would simply start the coroutine and continue, thus printing the "Done!" before the "Almost done..."
Debug.Log("Done!");
}

public IEnumerator DoIt() { // "public" isn't really needed in this example, but you need to use it if you want to call this function from outside this script!
Debug.Log("Doing it...");
yield return new WaitForSeconds(0.5f);
Debug.Log("Almost done doing it...");
}

//Output:
//Doing it...
//Almost done doing it...
//Done!
7 Comments

Unity: Making the Switch from Javascript to C#

First of all: It was a lot easier than I expected. And if you’re planning to switch as well, I hope I can make it even easier for you with this series of posts.
First I bought C# in a Nutshell, a very straight-forward book that teaches you almost everything you need to know in as few sentences as possible. Cheap and good – you really don’t need much else. It is, however, not Unity-specific and that is where I come in!

1) Variables and Types


JS
var size : float = 0.5;
var keyword : String = "Skylight";
var isOn : boolean = true;

private var hiddenVar = 0; //in JS variables are shown in the inspector by default and you have to mark them as private to hide them
var visibleVar = 1;


C#

float size = 0.5f; //you have to add an f to make it a float-value! (without the f it would be a double and wouldn't fit into a float variable)
string keyword = "Skylight"; //notice the lowercase s!
bool isOn = true; //notice: bool instead of boolean in JS!

int hiddenVar = 0; //in C# variables are private by default...
public int visibleVar = 1; //...and you have to mark them as "public" if you want to see them in the inspector or access them from another script

//Add the f even if you're not using a variable - if a function is expecting a float value, it won't take anything but a float!
GiveMeAFloat(0.25f);

2) Type Conversions (Casting)

You want to convert one type to another? Here’s how:

JS

var f : float = 0.08; // create a float
var i : int = f; //assign it to an int
print(i); // Done! - Result: 0

C#

float f = 0.08f; // create a float
int i = (int) f; // in c# you have to use explicit casts (the target type set in braces) if any information is in danger of getting lost during the cast
Debug.Log(i); //Result: 0

The other way around works without explicit cast though (as no information is in danger of getting lost)

int i = 5;
float f = i;
Debug.Log(f); //Result: 5
5 Comments

Unity: How to relay messages sent by AnimationEvents

Here’s a reusable script for preloading AnimationClips with AnimationEvents: (in Unity 2.6 you can do this directly in the new Animation Editor, but in Unity iPhone this is a nice way to do it)

//PreloadAnimClipWithEvent.js

var targetClipName : String = "idle"; //Where should the Event be added? (the name of the AnimationClip)
var throwTime : float = 1.3; //When should the function be called?
var throwFunctionName : String = "MyFunction"; //What's the name of the function?

function Start () {

var throwEvent : AnimationEvent = new AnimationEvent();
throwEvent.time = throwTime;
throwEvent.functionName = throwFunctionName;

animation[targetClipName].clip.AddEvent(throwEvent);

}

And since my scripts are never in the right place to catch messages sent by AnimationEvents, here’s a script to relay a message. If this script catches a message called RelayMessage it sends message to target. So just set the AnimationEvent to send a message named “RelayMessage” and then enter real target and real functionName here.
//RelayMessage.js

var target : GameObject;
var message : String = "FunctionName";

function RelayMessage () {

target.SendMessage(message);

}

To sum it up: With the first scripts you can add an AnimationEvent to an AnimationClip and with the second script you can easily relay that message from the gameObject that holds the animation to some other gameObject that is the intended recipient.

Leave a comment

Unity: Non Power of 2 Textures

Ever tried changing the texture import settings of 5+ images in Unity iPhone? – Yes, it’s painful. Luckily someone wrote an Editor Script that can automate the task and put it up on the nice Unify Wiki. (There’s a version for regular Unity available as well here)

I just added a new menu to the Unity iPhone version of this script that lets you automate the changing of the Non Power of 2 setting as well. And while I’m at it… What’s that setting and why is it important for iPhone development?
First the basics: The iPhone can use PVRTC-compressed textures and you might want to use this compression for 2 good reasons:
  1. It helps you keep your app install size down (a 512x512px image in RGB24 has about 768KB – in PVRTC 4bit it has 128KB)
  2. It will be harder for your app to blow up the texture memory. – If your game has a complex menu with 20 full 480×320 screens, it will most likely run out of memory and crash.
Now this is where the Non Power of 2 setting comes in. PVRTC can only be applied to textures that are square and to a power of 2 (128×128, 256×256, 512×512, 1024×1024 or 2048×2048). – Your 480×320 screens can thus not be compressed unless they are rescaled to a power of two. The non power of 2 setting gives you 4 options:
  • None – Keep the original dimensions
  • Scale to nearest
  • Scale to larger
  • Scale to smaller
Even if you choose to rescale your image you can of course still display it in it’s original size.
Yes image quality will suffer, but if I have to choose between a slightly blurry main menu and a crash, I’ll go with blurry…
It doesn’t always make sense to do this as changing a 320x20px strip from RGB24 to a 512x512px with PVRTC will most likely result in a larger filesize. I’m sure you get the general idea; same as everywhere: Thinking never hurts…
Oh, yeah, also don’t forget to turn off Mip-Maps for all your gui-images! Saves a few KB as well…
Leave a comment

OpenFeint Unity Integration

EDIT: This was written over a year ago and won’t help you with the current version of OpenFeint, sorry.
Integrating OpenFeint in a Unity iPhone project is pretty straightforward, just sign up, get the sdk and follow these steps. A few additional notes though…
Unity:
I didn’t really manage to access the OpenFeint singleton from Javascript, it kept giving me ‘singleton’ is not a member of ‘callable() as void’ . So I wrote a simple C# script just for calling OpenFeint and call that from Javascript:
using UnityEngine;
using System.Collections;
//Notice how no "using OpenFeint;" or something like that is needed!

public class OpenFeintStuff : MonoBehaviour {

public void LaunchOpenFeint () {
OpenFeint.singleton.launchDashboard();
}

}

SDK Integration (XCode):

ad 5: If it says Multiple Values next to “Other Linker Flags”, select only the active config, then edit the line. This is what it should read: -ObjC,-Wl,-S,-x



ad 6: The place to check for this is under Targets > Unity iPhone > Get Info > General – then look at the bottom and add the missing frameworks with the [+] button on the bottom left.
ad 11: Your product key and secret key need to look like this: @”x238476d-etc” (this is what strings look like in Objective-C)
5 Comments

Edge of Curling

Read more here, and also here, here and here if you got the time…

Leave a comment

Unity: Random Hint of the Day

Ever wanted to scratch (right-click-and-drag-to-change) transform values in Unity iPhone?
Ever wondered what the real names of the color-fields of a shader are? (If you want to do something like renderer.material.GetColor(“_SpecColor”))
Ever wanted to see your private variables in the inspector?
Ever noticed the little Debug Tab in Unity iPhone or the little Debug option in the Inspector Menu in Unity 2.5?
2 Comments

Unity: How to blow up a mesh like a balloon

Say you wanted to blow up a mesh like a ballon – simply scaling it up isn’t good enough. There’s an example in the documentation that teaches you how to move vertices along normals, but it doesn’t quite do what I want it to, since the mesh falls apart in the process:
Here’s the slightly modified code of the example, as seen in the video above:
function Update () {
var meF : MeshFilter = GetComponent(MeshFilter);
if(meF) mesh = meF.mesh;
     var vertices = mesh.vertices;
     var normals = mesh.normals;
     for (var i=0; i<vertices.length; i++) {
          vertices[i] += normals[i] * 2.0 * Time.deltaTime;
     }
     mesh.vertices = vertices;
}

To prevent this disintegration from happening we need to find all vertices that share identical positions and find one average normal per group of identicals. First the result, then the code:

private var mesh : Mesh;
private var vertices = new Vector3[0];
private var normals = new Vector3[0];
var finalNormals = new Vector3[0];

function Start () {
var meF : MeshFilter = GetComponent(MeshFilter);
mesh = meF.mesh;

vertices = mesh.vertices;
normals = mesh.normals;

//Find identical vertices
var vertexIDs = new int[vertices.length]; //this will hold an ID for each vertex, vertices at the same position will share the same ID!
var counter : int = 0;
for (var i = 0; i < vertices.length; i++) {
for (var j = 0; j < vertices.length; j++) {
 if(vertexIDs[i] == 0) {
  counter++;
  vertexIDs[i] = counter;
 }
 if(i != j) {
  if(vertices[i] == vertices[j] && vertices[i] != 0) {
   vertexIDs[j] = vertexIDs[i];
  }
     print(i + ", " + j + ":" + vertices[j] + " (" + vertexIDs[j] + ")");
 }
}
}

finalNormals = normals;

//Calcualte average normals
for(k = 1; k <= counter; k++) { //counter is the highest vertexID, now go through all the groups and collect normal data
var curAvgNormal : Vector3 = Vector3.zero;
for(l = 0; l < vertexIDs.length; l++) {
 if(vertexIDs[l] == k) {
  curAvgNormal += normals[l]; //Add up all the normals of the vertices with identical positions
 }
}
curAvgNormal.Normalize(); //Normalize the result
for(m = 0; m < vertexIDs.length; m++) {
 if(vertexIDs[m] == k) finalNormals[m] = curAvgNormal;
}
}
}

function Update () {
for (var i = 0; i < vertices.length; i++) {
   vertices[i] += finalNormals[i] * 2.0 * Time.deltaTime;
}
mesh.vertices = vertices;
}

This code is horribly inefficient though and calculating the average normals will take forever. (Unity will hang and the little colorful wheel will spin until it’s done) So don’t try this on any object with more than 200 or so triangles unless you have a lot of time… (please add your optimization tips in the comments below :])

Since the mesh is known from the start we could just as well pre-calculate the normals though, so that they don’t have to be calculated each time at startup.
A Simple and crude way of doing this: Run the game in the Editor >> copy the gameObject once the finalNormals have been calculated >> stop the Editor >> paste gameObject >> replace script with a version that lacks the normal-calculations and is only good for use with a script that already has the finalNormals set:
private var mesh : Mesh;
private var vertices = new Vector3[0];
private var normals = new Vector3[0];
var finalNormals = new Vector3[0];

function Start () {
    var meF : MeshFilter = GetComponent(MeshFilter);
    mesh = meF.mesh;

    vertices = mesh.vertices;
    normals = mesh.normals;
}

function Update () {
    for (var i = 0; i < vertices.length; i++) {
        vertices[i] += finalNormals[i] * 2.0 * Time.deltaTime;
    }
    mesh.vertices = vertices;
}

Okay, not bad. There’s still room for improvement though: It will look even more realistic (well, that is if you would classify “blowing up a wooden table” as “realistic”) if you also slowly scale up the gameObject with transform.localScale:

2 Comments