Disclaimer: this is an automatic aggregator which pulls feeds and comments from many blogs of contributors that have contributed to the Mono project. The contents of these blog entries do not necessarily reflect Xamarin's position.

May 23

Fresh Evolve 2013 Video Goodies Available

Straight from the Xamarin Evolve 2013 director’s room, we’ve just uploaded six great new videos:

  • Josh Clark’s Buttons are a Hack session, which mines a variety of surprising sources for interface inspiration and design patterns to help you understand and craft new gesture vocabularies.
  • Xamarin engineer James Clancey covers how to get the most out of Xamarin.Mobile, and
  • Xamarin engineer Marek Safar deep dives into the benefits and best practices for taking advantage of Async in your Mobile Apps.

In addition to posting these talks, we have enabled downloads for all videos from the show so that you can Evolve wherever you go. We have many more great iOS, Android, cross-platform and Enterprise Mobility talks still being finalized, so stay tuned.

A good workflow to smoothly import 2D content into Unity, Part II: Importing

Recently I wrote about authoring your 2D content in Photoshop and then setting it up for exporting. Today’s post will cover importing the files into Unity.  You can find a link to download all the files at the end of the post.

Picking up where we left off

Unity will happily import our images and XML file, but the images will be imported as normal textures by default, and the XML file will be imported as a text asset. So we need to write an importer within Unity to process the files for our game.You might think that writing an AssetPostprocessor would be the way to go and you’d be forgiven for thinking that. The problem with using AssetPostprocessor is that we’re limited in what we can do within that context and it won’t allow us to create a new material which we need to do. So the answer is to simply write an editor script to do what we want.

Our importer will need to:

  • Load and deserialize the exported XML meta-data,
  • Change the texture import settings for our images so that we can process them,
  • Create and texture atlas and pack all our textures into it,
  • Create mesh assets for each of our images,
  • Create GameObjects that reference the meshes,
  • And create a scene to hold our GameObjects.

Writing Editor scripts

As with the exporter, you can download the importer script here (). It should be placed in a folder called “Editor” in order for it to work.If you haven’t written editor scripts before you’re not taking advantage of one of Unity’s most powerful features. Editor scripts are a superset of normal scripting, so if you already know how to write game scripts you already know the basics of editor scripting too.

Editor scripts are distinguished from regular game scripts in essentially three ways.Firstly, editor scripts must be placed within a folder named “Editor”, or one of it’s sub-folders. Secondly, at the top of the scripting file you must place the following line:

using UnityEditor;

Finally, in order for the editor script to be called, it must derive from one of the editor sub-classes such as Editor, EditorWindow, ScriptableWizard, etc. You can use classes that don’t derive from these, but if you want to receive events and be interactive, these classes do so in a way similar to MonoBehaviour. For our purposes we’ll use the general Editor base class.

public class HogImporter : Editor
{
        ...
}

As with the exporter we won’t go over every line as the file is well commented, but let’s look at some of the more interesting bits.To start, we need some way to invoke our importer, so we’ll put it on the Assets menu inside Unity like this:

[MenuItem("Assets/Create/Import HOG Scene...")]
static public void ImportHogSceneMenuItem()
{
        ...
}

So now we are sitting in the Assets menu, and when chosen we can execute a script, so now all we have to do is do something useful.

The first thing we’ll do is convert the XML file to something more useable such as a data class. When we wrote the exporter, we organized our data into a logical set of elements so that it will map easily into a data class. Our data class looks like the following and matches our XML file in structure and data types:

public class HogScene
{
        public Layer[] layers;
        public enum LayerStatus { Active, Found };
        public enum LayerType { Custom, Item, Scenery };
        public class Layer
        {
                public LayerType type;
                public string name;
                public LayerStatus layerStatus;
                public Rect bounds;
                public Image[] images;
        }

        public enum ImageType { Hotspot, Obscured, Whole, Shadow, Custom, Count };
        public class Image
        {
                public ImageType type;
                public string name;
                public float x;
                public float y;
                public float z;
        }
}

To actually convert the XML file into the data class, we use the built-in .NET serialization methods.

HogScene hogScene = (HogScene)DeserializeXml(assetPath, typeof(HogScene));
...
static private object DeserializeXml(string filePath, System.Type type)
{
        object instance = null;
        StreamReader xmlFile = File.OpenText(filePath);
        if(xmlFile != null)
        {
                string xml = xmlFile.ReadToEnd();
                if((xml != null) && (xml.ToString() != ""))
                {
                        XmlSerializer xs = new XmlSerializer(type);
                        UTF8Encoding encoding = new UTF8Encoding();
                        byte[] byteArray = encoding.GetBytes(xml);
                        MemoryStream memoryStream = new MemoryStream(byteArray);
                        XmlTextWriter xmlTextWriter =
                                new XmlTextWriter(memoryStream, Encoding.UTF8);
                        if(xmlTextWriter != null)
                        {
                                instance = xs.Deserialize(memoryStream);
                        }
                }
        }
        xmlFile.Close();
        return instance;
}

Since we’ll be creating a scene using code, it’s possible that the user already has that scene open, or another, and we need to be sure they get a chance to save changes. To do this we call:

if(EditorApplication.SaveCurrentSceneIfUserWantsTo() == false)
{
        return;
}

Then we simply create a new scene, deleting the old one first if it already exists:

string scenePath = baseDirectory + baseFilename + " Scene.unity";
if(File.Exists(scenePath) == true)
{
        File.Delete(scenePath);
        AssetDatabase.Refresh();
}
// now create a new scene
EditorApplication.NewScene();

Next up is to fix the texture import settings. By default textures aren’t readable and we need to read them in order to put them into an atlas. While we’re at it, we also need to change some of the other settings.

List<Texture2D> textureList = new List<Texture2D>();
for(int layerIndex = 0; layerIndex < hogScene.layers.Length; layerIndex++)
{
        for(int imageIndex = 0;
                imageIndex < hogScene.layers[layerIndex].images.Length;
                imageIndex++)
        {
                // we need to fixup all images that were exported from PS
                string texturePathName = baseDirectory +
                        hogScene.layers[layerIndex].images[imageIndex].name;
                Texture2D inputTexture =
                        (Texture2D)AssetDatabase.LoadAssetAtPath(
                        texturePathName, typeof(Texture2D));
                // modify the importer settings
                TextureImporter textureImporter =
                        AssetImporter.GetAtPath(texturePathName) as TextureImporter;
                textureImporter.mipmapEnabled = false;
                textureImporter.isReadable = true;
                textureImporter.npotScale = TextureImporterNPOTScale.None;
                textureImporter.wrapMode = TextureWrapMode.Clamp;
                textureImporter.filterMode = FilterMode.Point;
                ...
        }
}

Now we’re ready to create the new atlas material, texture and pack everything into it.

// create material
string materialPath = baseDirectory + baseFilename + " Material.mat";
// remove previous one if it exists
if(File.Exists(materialPath) == true)
{
        File.Delete(materialPath);
        AssetDatabase.Refresh();
}
// make a material and link it to atlas, save that too
Material material = new Material(Shader.Find("Transparent/Diffuse"));
AssetDatabase.CreateAsset(material, materialPath);
AssetDatabase.Refresh();
// load it back
material = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material));
// make a new atlas texture
Texture2D atlas = new Texture2D(2048, 2048);
// to make an atlas we need an array instead of a list
Texture2D[] textureArray = textureList.ToArray();
// pack it with all the textures we have
Rect[] atlasRects = atlas.PackTextures(textureArray, 0, 2048);
// save it to disk
byte[] atlasPng = atlas.EncodeToPNG();
string atlasPath = baseDirectory + baseFilename + " Atlas.png";
if(File.Exists(atlasPath) == true)
{
        File.Delete(atlasPath);
        AssetDatabase.Refresh();
}
File.WriteAllBytes(atlasPath, atlasPng);

Since we have created all the basic parts we need, we can now loop over the images, create meshes, create the GameObjects and put them into the scene. It’s a fair amount of code so it isn’t repeated in it’s entirety, but certainly the most interesting part has to be creating the 2D sprites in Unity. You might be surprised to find out how simple and easy it is. I use a simple function to do it for all my 2D stuff within Unity and it looks like the following.

static private void ConfigureGo(GameObject go, Texture2D texture, Material material,
Rect uvRect, string meshPath)
{
        // create meshFilter if new
        MeshFilter meshFilter = (MeshFilter)go.GetComponent(typeof(MeshFilter));
        if(meshFilter == null)
        {
                meshFilter = (MeshFilter)go.AddComponent(typeof(MeshFilter));
        }
        // create mesh if new
        Mesh mesh = meshFilter.sharedMesh;
        if(mesh == null)
        {
                mesh = new Mesh();
        }
        mesh.Clear();

        // setup rendering
        MeshRenderer meshRenderer =
                (MeshRenderer)go.GetComponent(typeof(MeshRenderer));
        if(meshRenderer == null)
        {
                meshRenderer =
                        (MeshRenderer)go.AddComponent(typeof(MeshRenderer));
        }
        meshRenderer.renderer.material = material;
        // create the mesh geometry
        // Unity winding order is counter-clockwise when viewed
        // from behind and facing forward (away)
        // Unity winding order is clockwise when viewed
        // from behind and facing behind
        // 1---2
        // | / |
        // | / |
        // 0---3
        Vector3[] newVertices;
        int[] newTriangles;
        Vector2[] uvs;

        float hExtent = texture.width * 0.5f;
        float vExtent = texture.height * 0.5f;

        newVertices = new Vector3[4];
        newVertices[0] = new Vector3(-hExtent, -vExtent, 0);
        newVertices[1] = new Vector3(-hExtent, vExtent, 0);
        newVertices[2] = new Vector3(hExtent, vExtent, 0);
        newVertices[3] = new Vector3(hExtent, -vExtent, 0);

        newTriangles = new int[] { 0, 1, 2, 0, 2, 3 };
        uvs = new Vector2[4];
        uvs[0] = new Vector2(uvRect.x, uvRect.y);
        uvs[1] = new Vector2(uvRect.x, uvRect.y + uvRect.height);
        uvs[2] = new Vector2(uvRect.x + uvRect.width, uvRect.y + uvRect.height);
        uvs[3] = new Vector2(uvRect.x + uvRect.width, uvRect.y);
        Color[] vertColors = new Color[4];
        vertColors[0] = Color.white;
        vertColors[1] = Color.white;
        vertColors[2] = Color.white;
        vertColors[3] = Color.white;

        // update the mesh
        mesh.vertices = newVertices;
        mesh.colors = vertColors;
        mesh.uv = uvs;
        mesh.triangles = newTriangles;
        // generate some some normals for the mesh
        mesh.normals = new Vector3[4];
        mesh.RecalculateNormals();

        if(File.Exists(meshPath) == true)
        {
                File.Delete(meshPath);
                AssetDatabase.Refresh();
        }
        AssetDatabase.CreateAsset(mesh, meshPath);
        AssetDatabase.Refresh();
        meshFilter.sharedMesh = mesh;
        // add collider
        go.AddComponent(typeof(MeshCollider));
}

That may seem like a lot of code, but it’s actually quite straightforward and simple.Finally, after we built all our 2D sprite assets, we simply fix-up the camera so that it will render our scene pixel perfect like it was originally in Photoshop.

// setup our game camera
Camera.main.gameObject.AddComponent<HOGController>();
position = Vector3.zero;
position.z = -hogScene.layers.Length;
Camera.main.transform.position = position;
Camera.main.isOrthoGraphic = true;
Camera.main.orthographicSize = (768.0f/2.0f);
Camera.main.nearClipPlane = 1;
Camera.main.farClipPlane = hogScene.layers.Length + 1;
RenderSettings.ambientLight = Color.white;

If you look through the importer you should be able to follow it pretty easily.

If everything went well, after running the importer script you should see the scene fully composed and running in Unity.

You can download a Unity package with all the files for this tutorial.

May 21

Putting the power of Unity in the hands of every mobile developer

Our simply big idea has always been to make game development accessible to more people with better tools. To help developers fulfil their creative vision and build their businesses.

Simple to say, hard to do!

Unity’s a restless company, and we’re continuously challenging ourselves to make the many complex decisions that it takes to push Unity forwards. We’re lucky to have assembled the most incredible bunch of people I know to do this work together, night and day (almost), and across geographies and time zones.

Today, we’re taking another step on this long road: as of right now, independent Unity developers will be able to deploy their games to Android and iOS platforms completely free of charge. Update Unity and you will find Android and iOS build options (previously basic add-ons) ready and waiting for you to use.

There are no strings attached, no royalties and no license fees. This is just an extension of Unity Free which we launched in 2009. Individual developers and startup studios can simply download Unity and get going on mobile game development. As before, companies and other “incorporated entities” (you know who you are) with a turnover in excess of $100,000 in their previous fiscal year are required to use our paid version. That way, we can keep the lights on and continue to make Unity better for everyone.

(You can make as much money from your games as you like – this limitation is about large companies not using our free products, not about sharing your future revenues.)

And we’re not stopping there. In the coming months, we will make Blackberry 10 and Windows Phone 8 deployment available to everyone all over the planet on those exact same terms. Completely free of charge.

I can’t wait to see what you make.

David Helgason

P.S. Within the next two weeks, we’ll be reaching out to those of you who purchased basic add-ons in the 30 days before they went free to offer you discounts on future purchases. Remember that purchasers of basic add-ons qualify for rebates should they choose to buy Unity Pro Android / iOS licenses.

P.P.S. Windows users can update Unity by opening the editor and selecting Manage License / Check for Updates from the Help menu. Mac users can update Unity by opening the editor and selecting Manage License / Check for Updates from the Unity menu.

May 20

Plastic SCM 4.1.10.440 External Release is out!!

Plastic SCM 4.1.10.440 (Kiev) is published now!

Take a look at the full list of changes is here. Visit the Plastic SCM download page to install or upgrade your Plastic SCM setup.

You can suggest and vote new features on the Plastic SCM Forum page and tell us your opinion about Plastic SCM or use the User's Voice channel, as well.

Let's see what's new in this release:


Bugfixes

  • When a local move was applied, the operation may fail showing an improper message: "Selector can't locate a revision for the item...". This issue was happenning because the local moves were not taken into account properly as depedencies. Now this is fixed.
  • Fixed some issues when using Plastic SCM with Mono 3.0. This version is not provided in our installer, but it's good to know that if you want to use it, now you can, and it should work like a champ.
  • Merge: An error was thrown when running a merge on Windows platforms that implied changing the contents of a symlink. This is now fixed.
  • Checkin: When this operation was performed from the GUI and there were not only small files implied (> 4Mb), the progress was not updated correctly for those files. Plastic SCM should show an additional progress for those files, but it didn't. Fixed.

Enjoy!

May 17

A good workflow to smoothly import 2D content into Unity, Part I: authoring and exporting

Unity has been used to develop numerous high quality 2D games over the years. This article, which is based on a talk I gave at three of our regional Unite developer conferences in Korea, Japan and China, gives in-depth instruction for a solid, real-life 2D production workflow. I hope this post can be helpful for any of our readers that are creating 2D games and interactive content with Unity. Due to the length of the tutorial, I’ve split it into two blog posts. Today you can read about authoring and exporting and tomorrow I’ll post the section on importing. You can find a link to download all the files at the end of the post.

The benefits of a good 2D content workflow

This tutorial takes you through the implementation of a real production workflow. When we talk about workflow it means the steps and processes used all the way from the initial authoring until the content is actually running in the game. Regardless of the number of applications needed in the chain from beginning to end, at a high-level a workflow consists of 3 major steps: authoring, exporting and importing.

For some it may seem odd that we need both an exporter and an importer since tools like Unity are able to import data directly. The reason we need both is because we’re essentially creating our own intermediate file format that acts as the glue between any two applications in your workflow, in this case between Photoshop and Unity. This eliminates the need for an external application to be able to read and parse an application’s native file format, and allows chaining of applications to process the content as it moves from one application to the next.

Authoring

It all starts with great content, and the first workflow we’ll look at is using the industry standard workhorse Photoshop. One of the great things about Photoshop is it’s simplicity to get started. Creating and editing imagery and graphics is painless and easy, and as your needs grow there’s an arsenal of tools and techniques at your disposal. The problem is that image files by themselves don’t have much ability to express useful meta-data for games in the same way that 3D models are able to do. What’s more, 2D is inherently in need of more meta-data given it’s limited nature of just being pixels.

So what we want to do is imbue the image with useful information so that ultimately we know how to use the image in a game. To do that, we can use groups and layers to organize and tag them with what we need.

We also need an example of 2D content that is useful and represents a realistic use. One of the last games I worked on before joining Unity was a simple 2D hidden-object game called Goddess Chronicles, and so we’ll use that as an example. In a hidden-object game the general idea is to find certain items that are hidden in plain sight in a scene such as the example shown below.

Depending upon the game you’re making, the meta-data you need to capture will be different. For this game the design called for 2 basic kinds of imagery: “scenery” and “items”.

The importance of layers

Scenery is the non-interactive content that’s there to provide the bulk of what’s seen, communicate a theme and support the gameplay by providing an environment where items can be hidden. So scenery will be placed into a group named “scenery” and we don’t need to care about the art layers in that group because they’re non-interactive. The items are the things you’ll actually be searching for within the scene and comprise the core gameplay. These are placed in groups that are named “item” and, unlike scenery, the art layers are important and each item can have up to 4 unique layers associated with them.

“Whole” layers are required for all items. Usually once an item is found there will be some effect such as zooming the item up, or placing it into the player’s inventory, and we need the whole image so that it looks right.

“Obscured” layers are used when you want to create the illusion that an item is behind something when in fact it’s floating in front of it. By erasing the pixels that should be hidden it tricks the eye into thinking that it’s actually behind something. In theory we could use whole images for everything, but there are many situations when it’s tedious for the artist to draw everything as separate pieces in order to hide an item, plus using the minimal amount of images in the game will increase the runtime performance.

“Shadow” layers are used to help visually place the items into the scene and look like they belong there. Shadows are kept separately from the whole or obscured image so that if the whole image is zoomed up or moved it doesn’t have an odd looking shadow following it, and instead we can just hide the shadow in the scene once the item is found.

“Hotspot” layers are used to increase or decrease the area which the item can be interacted with. For example if you hide a golf club in a scene it could be very difficult to click or tap on. By using a hotspot you could make the interaction area bigger and easier to use.

So putting all this together we can use groups to designate whether something in our scene is scenery or an item, and we can use the art layers for items to hold the whole image for the item and optionally include obscured, shadow and hotspot images. The image below shows a set of layers for some scenery and an item. The item group is labelled “item:Beads” and contains 2 art layers called “whole” and “hotspot”. The scenery group is labelled “scenery:Column” and it contains any number of art layers that can be named anything since scenery layers aren’t special and we don’t need to keep track of them.

The end result is that we have a well composed scene where the group and layer names are encoded with what we need to give them meaning in our game. You can download the package at the end of the post and have a look for yourself. The next step is to now get all this exported.

Exporting

Once we have some content, we need some way to get it all out for the next application in our workflow, which in this case is Unity. What we want to export are the images used to construct the scene along with the meta-data describing the position, order and other information. In order to do that we need a way to interact with the application at a low level with something that understands how to do that. Fortunately for us, Photoshop is scriptable using javascript and this will do exactly what we need.

In fact quite a few Adobe apps are scriptable including Fireworks, Illustrator, Flash and others. We can use this capability to write our own exporter that can prepare the images for use in Unity and also capture the meta-data we need to make them meaningful. Adobe provides useful documentation and a script editor and debugger called ExtendScript for free.

If you have the Creative Suite, it’s probably already installed on your system. On Mac it can be found in the Utilities/Adobe Utilities – CS6/ExtendScript Toolkit CS6 folder for the latest Creative Suite. On Windows, you should be able to find it at C:\Documents and Settings\\Application Data\ Adobe\ExtendScript Toolkit\3.8.

Pretty much anything you can do in Photoshop can be scripted, and if there isn’t an API for a particular thing you want to do, you can record actions and convert them to command codes that you can paste into your scripts (alpha channel operations, I’m looking at you!).

For our purposes, we need a simple script that basically:

  • Checks to see if we have an open document,
  • Makes sure the document has layers to export,
  • Prompts the user as to where the exported files should be placed,
  • Loops through the layers from back to front, trimming away the empty space, saving the image to disk and capturing the position and filename in an XML formatted string,
  • And finally saving out the XML data to a file.

The final exporter script is in the tutorial package. To use the script you place it in the Presets/Scripts sub-directory inside your Photoshop application directory. The script contains comments that explain what it does so I won’t go through all of it, but I will cover some of the more important parts.

Firstly, the scripts are written in javascript which makes it easy to learn and use. The javascript engine used by Adobe isn’t very fast, but it works and is debuggable with the ExtendScript editor which makes it very useful.

Since the meta-data is actually the part that gives meaning to the data, we need to spend the most time figuring out exactly what meta-data we need and how it should be formatted. I use XML as the way to specify the meta-data since that makes it really easy to parse later on in Unity. Based on the game design we know we have certain data that will be needed in the game. An extract of that data looks like this:

<?xml version="1.0" encoding="utf-8"?>
<HogScene xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <layers>
                <Layer>
                        <type>Scenery</type>
                        <name>Scenery 01-4 background</name>
                        <images>
                                <Image>
                                        <type>Whole</type>
                                        <name>Scenery Tree.png</name>
                                        <x>25</x>
                                        <y>63</y>
                                </Image>
                        </images>
                </Layer>
                ...
        </layers>
</HogScene>

So our exporter script will capture these simple XML elements during export and when it’s all completed write that out to a file.

In our exporter script, we start off with creating some file scope variables that we need for convenience and then call the “main” function which is defined right after that. The basic way this works is that when you run your script it’s evaluated and executed from top to bottom. You find examples on the internet where some code is contained in functions and some is not, and I find this a bit confusing. So I put everything into functions and call the entry point explicitly as a matter of convention.

Inside the main function, there’s a couple of interesting parts. The first one is the line:

duppedPsd = app.activeDocument.duplicate();

Duplicating the active document is highly recommended for two reasons. The first is that in Photoshop if you touch anything in a document, even expanding or collapsing a group, it causes the document to be marked as dirty. So if we didn’t duplicate the active document, the process of exporting would always cause it to be marked as dirty. When the artist quits Photoshop or closes the document they will be prompted to save, and they may not remember if they made changes to the document or not and will likely just save it. This will cause the timestamp of the file to be newer than the exported files, and once checked into version control will be confusing because a designer, producer or programmer won’t know if they need to re-export the file or not. This creates an endless cycle because the file will always be newer than the export. By making a duplicate it will leave the original document in it’s original state, which still may cause a problem, but that’s then a production process problem and not something we’re causing.

The second reason for duplicating the document is simply that things will go wrong while creating your own exporters, and when things go wrong it will leave your document in an unknown state. So by duplicating it we always have our untouched master copy to work with.

The next thing of interest in the main function is:

removeAllTopLevelArtLayers(duppedPsd);

Since we’re using groups as the containers for the things we’re interested in, we can let the artists or designers add art layers that aren’t in any group (“top level”). They can use this for concept or photo references, screen layout guides, or placing placeholder elements like a game HUD. So we clean up the duplicated file by removing these images before processing.

Other than that, the main function calls the export function, then creates and writes the XML file containing our meta-data.

The export function exportLayerSets is a recursive function. A recursive function means it calls itself if needed to “drill down” into our groups to find the lowest level group that is deepest in the scene.

function exportLayerSets(obj)
{
        for(var i = obj.layerSets.length-1; 0 < = i; i--)
        {
                exportLayerSets(obj.layerSets[i]);
        }
        ...
}

It does this by simply looping backwards through the list of groups, and if one of the groups has a group inside it, then it recurses and calls itself again with that group and so on. We loop backwards because in Photoshop the bottom-most layer in the list is the first one and groups and layers higher in the list are drawn on top of lower ones. So we process everything back to front.

Once we have an actual art layer, we then look at the group name and see if it starts with “item:”, “custom:” (which we used for HUD elements) or else it’s assumed to be scenery.

if(obj.name.search("item:") >= 0)
{
        ...
}
else if(obj.name.search("custom:") >= 0)
{
        ...
}
else // must be a scenery group
{
        ...
}

For items, we then loop through the art layers, switch on the layer and export whichever of the known types we support.

// process layers
for(var layerIndex = 0; layerIndex < obj.artLayers.length; layerIndex++)
{
        sceneData += "<Image>";
        obj.artLayers[layerIndex].visible = true;
        switch(obj.artLayers[layerIndex].name)
        {
                case "hotspot":
                        saveScenePng(...);
                break;
                case "obscured":
                        saveScenePng(...);
                break;
                case "shadow":
                        saveScenePng(...);
                break;
                case "whole":
                        saveScenePng(...);
                break;
        }
        obj.artLayers[layerIndex].visible = false;
        sceneData += "</Image>";
}

When we find something we want to save, we call the function to save the image as a PNG file. This function collapses the image and trims the left and top in order to determine the X and Y coordinates of the image. Then we trim off the right and bottom and save it out, and capture the meta-data into the XML string.

function saveScenePng(psd, imageType, fileName)
{
        // we should now have a single art layer if all went well
        psd.mergeVisibleLayers();
        // figure out where the top-left corner is so it can be exported
        // into the scene file for placement in game
        // capture current size
        var height = psd.height.value;
        var width = psd.width.value;
        var top = psd.height.value;
        var left = psd.width.value;
        // trim off the top and left
        psd.trim(TrimType.TRANSPARENT, true, true, false, false);
        // the difference between original and trimmed is the amount of offset
        top -= psd.height.value;
        left -= psd.width.value;
        // trim the right and bottom
        psd.trim(TrimType.TRANSPARENT);
        // find center
        top += (psd.height.value / 2)
        left += (psd.width.value / 2)
        // unity needs center of image, not top left
        top = -(top - (height/2));
        left -= (width/2);
        // save the image
        var pngFile = new File(destinationFolder + "/" + fileName + ".png");
        var pngSaveOptions = new PNGSaveOptions();
        psd.saveAs(pngFile, pngSaveOptions, true, Extension.LOWERCASE);
        psd.close(SaveOptions.DONOTSAVECHANGES);

        // save the scene data
        sceneData += ("<type>" + imageType + "</type>
                                <name>" + fileName + ".png</name>
                                <x>" + left + "</x><y>" + top + "</y>");
}

When we run the exporter on the file, we should end up with a directly of cropped PNG files plus an XML file with the same base filename as the original document such as that shown below.

Now that we successfully exported all our images and meta-data, we move to the next application in our workflow which is Unity and get the files imported. I’ll cover this in my next blog post. Thanks!

You can download a Unity package with all the files for this tutorial.

May 16

2000 checkins per minute and counting

Do you want to know how Plastic SCM performs under really heavy load? If you’re a Plastic enthusiast or just want to learn about the product… then keep on reading.

Why are we so obsessed with performance and scalability?

Version control performance is a critical point for lots of software teams out there. It is not restricted to a single industry: you can have big teams with big projects in aerospace, game dev, finance, telecom and many more. And the thing is that sometimes they can’t work in a distributed fashion, so they put a big burden on the version control server shoulders...

That’s why we regularly run load tests in Amazon to simulate lots of version control users putting a huge load on a single server… And this time we’re going through a quite interesting scenario: how does the server react when it is under a 2000 checkins per minute load?

The big “gang” theory

Big is a concept that changed quite a lot for us while evolving Plastic over the years. I still remember our first ever full checkin of the quake source code that we used for testing. It is not bigger than 1200 files (twelve hundred) but it took… a while. It was back in 2005.

Later we considered big a source tree around 20k files.

But things changed and today a good source tree is one with about 500k files and 40-80k directories and a big number of Gb in the working copy. And big, really big, is 1.5 million files.

What we consider a big number of concurrent users also grew up a little bit: back in the day 50 was sort of ‘hey, are they trying to crash it’ but today we’ve customers with 1200 concurrent coders on the same project on a daily basis… on a 350k files source tree.

The phantom bots menace

Here is the scenario we’re talking about: 300 bot clients crazily loading a single server. The point is not really figuring out how much load the server can handle, today the question is: as a developer doing regular operations, how much I am affected if my server is under heavy load?

Or, in other terms: as a developer, can I work smoothly in a big team or will team size be a bottleneck for the server and hence even the simplest operation will be taking ages?

That’s why the scenario is as follows (thanks to our designer :P): 1 human developer doing operations while 300 bots overload the server with concurrent operations at 2000 checkins per minute on a 350k files repository loaded up with a good changeset count.

Why not distributed?

You might ask: “hey, but Plastic SCM is a Distributed Version Control System, why are you using a central server instead of each developer checking in to their own servers hence removing the bottleneck??”

The answers are:

  • Yes, we can do that: use the distributed mode “if you can” and problems are over.
  • Noticed the “if you can” in the bullet point above? It is there for a reason: there are cases where distributed is not an option, at least not the option for everything.

When distributed is not an option

You read right: sometimes teams can’t go fully distributed. There are some reasons for this:

  • Not every team member is a programmer used to the dvcs paradigm. So asking them to checkin AND push is an overkill.
  • The repo is SOOO big that for whatever reason you don’t want to have a copy on each team-member machine. We can go around this one with Plastic SCM because we allow “partial replica” (a quite unique feature that cost us some headache to implement but now it is helping us to get more traction) but it is still not an option for some teams.

There are more options, but these two are a reality for many teams, especially in the gaming industry.

A few more reasons (for game devs) why “conventional” dvcs gets out of the picture:

  • They need exclusive checkout for artists. They DO need it. This one normally puts git and mercurial out of the table. Plastic supports exclusive locking even on distributed scenarios. We implemented a global list on a server acting as ‘lock master’ that the rest of servers can check (you can’t lock while you’re offline… which is doable but would be quite complicated and error prone).
  • They have also big files (like 1Gb or more) which also tends to be “game over” for Hg and Git and opens Plastic the doors.

But still, sometimes big teams working on big projects (and this can be true for smaller teams dealing with big projects too), simply want to simplify things: 1 server per location (running replicas across the different sites and taking advantage of both the distributed nature of the product plus the partial replica) and team members accessing the site server, plus only some of them working replicated on their laptops, at home and so on.

Then what is the issue with traditional centralized servers?

Easy, can’t scale while branching and merging in a big team (they have problems with small ones too, but it simply explodes on big ones).

If creating a branch takes ages (like minutes or so) or if your backend gets locked on a frequent basis… then you’re in trouble.

As you all know, the version control business is about replacing existing products on teams: almost everyone has a version control nowadays, so our job with Plastic is to probe we’ve more features, we’re faster, easier… the usual :P

But we’ve tough competitors so that’s why we have to create this sort of tests to show what the server can do.

Setting up the server

The server we used for this test is one of the biggest we set up for testing so far: 16 cores and 60Gb RAM.

But the Plastic server binaries are always the same whether they run on a laptop using 80Mb RAM or in a big loaded test server using lots of system memory.

There are some tweaks to consider, the main one is the number of “trees” to be cached in memory. Since Plastic SCM 4 the server deals a lot with “changeset trees”, basically the source tree you have on a certain cset. Since different changesets tend to share most of their source trees, caching them is fast and easy.

When you run Plastic on your laptop the server normally has to deal with only a single user, so it is all about having only a few trees cached (the one you’re working on basically) and loading more on demand (reusing most of the nodes) whenever you merge, diff or switch to a different branch.

But in order to speed things up for a big team where users will be requesting lots of trees, it is good to keep as many of them in memory.

This is the main tweak we configure for big servers: modify db.conf and add:


<MaxCachedTrees>50000</MaxCachedTrees>

Which will cache up to 50k trees (and the number can be bigger if you need to).

There are also options for servers under really heavy load which allow them to load the most recently used trees on startup prior to begin serving clients and hence reach a stable status ASAP. In order to set it up you can add the two following entries to db.conf:


<LastUsedCsetsLoad>40</ LastUsedCsetsLoad>

Which specifies the size of the LRU cache.


<LastUsedCsets>c:\cache\cache.txt</LastUsedCsets>

The file to cache all the info.

Bot clients

In order to create the clients we used what we call a “carnage test” (the name says it all) which is an executable file using the PNUnit framework (our extension to NUnit to create distributed tests) and linking to the Plastic internal client API.

This way we can create quite lightweight clients that use less resources than a regular one (for instance they do not create a regular workspace but run all operations in memory so putting even more burden on the server shoulders) and are quite easy to run with virtually no setup.

The watcher

While the bots are running we run some manual operations on a client machine to check how it is affected by the server being under heavy load.

In the past we just measured bots finishing their workloads, which is ok but it doesn’t really give you a perspective about “how does it look like to work on a server used by lots of developers”.

Numbers measuring completion time for 300 clients just tell you whether it scales or not (or it just multiplies by “n” the single user test result) but not really the feeling.

Next steps

Once we went through the initial tests we’re creating a much bigger repository with about 3+ years of history and a different type of “bot client”: something really simulating a developer instead of crazily doing operations and burning CPU.

The well-finished load test page

We’ve created a quite interesting page describing the scenario here and including a screencast of the “watcher” client.

Lvov Game Hackathon – the view from inside

Hi everyone! I want to share with all of you the news on Game Hackathon that took part in Lvov, Ukraine last weekend.

Unity Technologies was one of the sponsors, Ilya Turshatov and I gave a short presentation and were present there as mentors for those loooong 30 non-stop coding hours.

The format of the event:

  • Teams up to 5 people
  • 30 hours to develop your game (you are allowed to use frameworks and engines)
  • 5 minutes to present your game
  • The jury chooses the winners according the following criteria: game play, technologies used and innovations

Some statistics:

  • 61 participant
  • 20 teams at the beginning and 18 teams that actually made it to the end.  5 teams used Unity. There was one game on Flash, some even used HTML tables and jQuery.
  • 264 cans of RebBull drunk
  • 70 pizzas eaten
  • 18 table football matches played
  • 6 movies watched

Winners and some more…

The most pleasant part was that the 1st and the 3rd places were taken by the games made with Unity!  And the overall impression was that games made with Unity looked more finished, stable and with no obvious bugs during the presentation.Now a bit about the projects themselves. I will mention only some of them, which we found the most interesting, though I must admit that all projects were quite compelling.

“Tomato Wars”

by Patriotic Games won the 1st place by the jury’s decision, as well received 2 Mobile license (which they needed) from us. The game play was “bloody”. You are a tomato and you have a rifle and you make tomato juice from all other tomatoes that attack you in packs. The choice of the guns is available, all the objects are breakable. Oh, oh… and you have bombs *evil laugh*.

“Titanium”

by Empty. by Empty. Shake, rotate, turn – do whatever you want to get those damn’ rings on the Titanic’s funnel. Quite addictive, the girls from the HR department were constantly asking for updates every now and then during the Hackathon. They got the 3rd prize and also received Unity licenses.

“Divine Path”

by Creators.   A student and two schoolchildren created the whole new world (Asset Store rocks!).  It was not something extra impressive, but for 3 guys with no actual experience it looked not bad, and in some cases it looked more compelling than the projects made by professional developers. The main concept of the game was the lost world with no people left where your main goal was to find the evil god. You wouldn’t find any tasks or hints in this game (as according to Creators it’s too boring just to carry out the missions), as well as you cannot exit the game so easily J Before leaving you need to find the “save point”, e.g. the doors in the house. They received 1 Unity license as an encouragement not to quit the attempts, and to go on with their experiments.

And here are some photos from the event.

May 15

Broaden your reach with multiplatform publishing

Develop once deploy anywhere – that’s our proud boast. Currently, users can deploy content built on the Unity engine to nine different platforms, and in recent months we’ve announced support for seven more: Windows Phone 8 and Windows Store, BlackBerry 10 and PS4, PS Vita, PS Mobile and Sony’s new cloud gaming service. Plus, we’re working closely with Facebook to improve the Unity Web Player experience for Facebook gamers.

Designing content for multiple platforms becomes far easier if you think a few things through before you start. If you get your processes right, it’s easy to use Unity to build high wow-factor games across a range of devices.

Ten top multi-platform tips

 

1. Does this make financial sense? It sounds obvious but, before starting your project it’s as well to think carefully about the financial benefits of deploying your game to multiple platforms. On the one hand, making a successful game available on just one platform ignores easily acquired additional revenue. On the other, the costs involved in porting your game go beyond simply acquiring an additional add on license and clicking publish.

2. What about my demographic? Different platforms have their various strengths and weaknesses and are more or less widely used in varying contexts. Consider whether the type of interaction and game play your game is based around is suited to deployment to the platforms you’re targeting.

3. Start with your two most widely divergent platforms. If you plan on developing a game for three or more platforms, it makes sense to start by weighing up what you need to do to get your content to outlying platforms. By considering this first you will automatically cover much of the ground involved in developing content for your remaining platforms.

4. Beware obsolescence. Mobile platforms change at bewildering speed and supporting legacy versions of a platform that are becoming more obsolete by the day may, ultimately, just add to your costs.

5. Abstract out platform-dependent plugins. If, for example, you plan to build leaderboards and achievements for Apple’s Game Center be sure to build a leaderboard manager which abstracts the leaderboard calls and then makes the Game Center calls. That way it’s easy to add, for example, SteamWorks leaderboard support later on.

6. Ensure resolution independence. Plan how your HUD, UI, on-screen controls and buttons will be depicted at various aspect ratios. Design the UI layout in a modular way so you can space out elements without a re-design. Remember that, in Unity, you can specify resolutions in percentages.

7. Build high res source art. Let Unity do the downsizing for you. This prevents late-stage art reworking for e.g. iPhone Retina displays. Plus, when you need poster-sized promotional art, you won’t want to cry.

8. Think optimisation into mobile games from the start. Use light probes to store lighting information and bake this information into dynamic objects, work with simple specialized shaders and detailed, high-contrast textures, use object pooling techniques and profile early and often.

9. Consider investing in additional tools. Owlchemy Labs’ Multiplatform toolkit is available from the Asset Store. Amongst other things this end to end solution can ease scaling, strip redundant assets from your platform-specific build and help you manage and apply global asset compressions.

10. Frequent use of compiler directives. Unity supports platform specific compilation so you can partition your scripts to compile and execute a section of code exclusively for a specific platform.

May 14

Power of mathematics: Reasoning about functional types

One of the most amazing aspects of mathematics is that it applies to such a wide range of areas. The same mathematical rules can be applied to completely different objects (say, forces in physics or markets in economics) and they work exactly the same way.

In this article, we'll look at one such fascinating use of mathematics - we'll use elementary school algebra to reason about functional data types.

In functional programming, the best way to start solving a problem is to think about the data types that are needed to represent the data that you will be working with. This gives you a simple starting point and a great tool to communicate and develop your ideas. I call this approach Type-First Development and I wrote about it earlier, so I won't repeat that here.

The two most elementary types in functional languages are tuples (also called pairs or product types) and discriminated unions (also called algebraic data types, case classes or sum types). It turns out that these two types are closely related to multiplication and addition in algebra...

Unity Training

Hello!

Just over a year ago I joined Unity as a Trainer and Consultant. In this role, I’ve been travelling to customers around the world helping them learn how to get the best from our technology. I’ve visited games companies, universities, research centres and simulation customers, and the locations have spanned the globe, from Texas to Saudi Arabia, to Singapore. (TL;DR Videos Below!)

During this time, I’ve also been helping to build up the range of training material that we can offer to customers. A lot of this material has grown organically, some based on customer requests for training in specific areas, and some based on creative ideas that tie together Unity’s features into learning projects.

The style and focus of the training courses vary widely. I’ve visited customers who needed a crash-course for their junior developers, or training for experienced developers moving to Unity from a different environment. I’ve also visited teams of experienced Unity developers in the middle of projects who wanted a quick boost of technical knowledge to help get their project to the finish line.

In my beginner crash-course, I take trainees on a tour through Unity’s main features, bringing everything we learn together into a finished game – which usually involves plenty of flying saucers, explosions and sound effects. This seemingly simple project covers many of Unity’s core features such as the art and asset pipeline, physics, components, scripting, prefabs, particle systems, audio, and helps get developers who are new to Unity familiar with the editor.

A common request from games and simulation customers alike is training for our new animation system, and its integration with physics and pathfinding. For this, I run through the entire system from scratch, creating a third-person controller and NPC characters with many of the common games actions such as mouselook, strafing, sprinting and crouch walking. We learn how to import, edit and retarget animations, through to building up state machines and integration with input. We examine how to get the pathfinding system to properly control root-motion animated characters, and how to make sure our characters can interact with physics objects properly. This whole section takes about two days to complete, and serves as a solid foundation of knowledge for building character-based games in Unity.

Simulation customers often want to build applications for training purposes themselves, and the individual requirements in the Sim field vary so much that there’s no one-size-fits-all training program. Their goals can range from small mobile applications showing how to maintain a piece of equipment, to virtual reality workplace safety training, to ocean-going container ship simulation, and the training I put together for each customer attempts to meet these needs, giving them the understanding they require to make the best use of our tools.

One project I use for Sim customers begins with a model of a stapler. I show the trainees how to start with the bare 3D assets, and build up an interactive training application which allows an end user to progress through the maintenance steps. Obviously the point here is not to teach how to use a stapler! – what the trainees learn are the skills required to build whatever kind of equipment-based training applications they need.

The videos below show a broader cross-section of the content of training we’ve delivered so far to customers.

If you want to learn more about Unity and want training, contact your account manager to find out more.

Unity Training – Basic

Unity Training – Games Focus

Unity Training – Sim Focus

Plastic SCM 4.1.10.436 External Release is out!!

Plastic SCM 4.1.10.436 (Bombay) is available now!

The full list of changes is here. Visit the Plastic SCM download page to install or upgrade your Plastic SCM setup.

You can suggest and vote new features on the Plastic SCM Forum page and tell us your opinion about Plastic SCM or use the User's Voice channel, as well.

Let's move on to the meat ;-)


New

Closable wokspace tabs: This feature has been suggested by lots of users and now it's available!


Take into account that you won't be allowed to close the latest workspace. This is because a workspace at least is necessary to work with Plastic SCM GUI.

To make a closed workspace visible again, you need to open the workspaces view and make that workspace active:




Bugfixes

Switching to a workspace that contained multiple opened views with a SEID condition (such as owner='me') could lead to a "Item has already been added" error. This concurrency but minor issue has been fixed.


Enjoy!

May 12

How four indies conquered Kickstarter Part II

Last Friday we published Part I of our story on how four indie customers successfully funded their games with Kickstarter. Part I focused mainly on the content the teams worked hard to produce before launching their Kickstarter projects, and how that effort paid off in attracting backers and press coverage. In today’s post the customers talk about how they spread the word for the project, budgeting, and the positive power of community.

Kickstarter logo

Start spreading the word as soon as you press Go, and target the audiences you know will want to play your game.

“We targeted sites and blogs where there is a high concentration of people interested in RPGs, like RPG Codex”, says Jonas. “We knew our target audience and we found them and talked to them. Even though the audience for some of the RPG sites we targeted is smaller than that of general news sites, the quality of the exposure we got was much more valuable”.

Jake and Tamas spread the word through their Chicago-based community of developers. “It’s a great community here of independent developers that really helped us out”, says Jake. “I also emailed my contacts at blogs like rock paper shotgun and indiegames.com. Within a week of launching we met our funding goal and over the next three weeks we earned an extra 15-20% on top”.

Klaus says they benefitted from enthusiastic backers who have their own networks who promoted their project. “You can actually follow people on Kickstarter and get a notification when they back a project. So they end up acting as a kind of ambassador for your game”.

About the money: Set a realistic and modest funding goal, offer nice rewards not just for the highest tiers, but the most popular ones, and be prepared to learn as you go along!

Jake says that when it came to their funding goal, “we decided to be really specific about where all the money was going. Kickstarter is still a really valid option for just starting out and setting realistic and precise goals, such as ‘I need $200 to pay an artist or $300 to pay the band’”.

Michael and Aaron set their funding goal for the minimum amount they needed to complete Blindside and anything above that would go towards extra production value. “You should also expect to lose about 10% of what you raise to fees for payment services, to Kickstarter itself, and to people whose credit cards don’t work”, says Aaron. “And make sure your tax structure is correct! You don’t want to end up raising a lot of money and then losing a big chunk of it to poor or incorrect tax reporting”.

By reading up on other Kickstarter campaigns, the team at Logic Artists learned that the most popular tiers are 15 or 30$. “So, you want to get people to pick $30”, says Jonas. “We offered beta access for $30. But it’s is hard to figure out what rewards should go with what tiers, especially the high-level tiers. What kind of reward do you offer for $10,000?”

Jake and Tamas also provided physical rewards, such as posters and CDs. “We did a really bad job of budgeting the time it would take to make the items and forgot to include shipping costs, so it cut into the money, but we made up for the loss with some of the extra funding we got”.

“Tiers are a huge thing to nail the campaign”, says Klaus from the Back to Bed team. “We figured out early on that we’d have to make new tiers with physical rewards. People reach a limit where they don’t want to pay for digital items, they want t-shirts. One reward we offered was a framed piece of artwork, and that was quite successful”.

And beyond the money: Whatever happens, take the long-term view that you are building up a new community of people interested in your work

“Now we have this community for our game! We’ve even had to hire a community manager”, says Ali from Logic Artists.

“We’re all invested in the game now”, says Jonas. “We use our Kickstarter community as testers and get a lot of valuable feedback. We even gave them access to our bug trackers”.

“It’s been really nerve wracking. We bet our reputation on it and it was so much work. But Kickstarter has been a way for us to show our skills and make a name for ourselves as a brand new studio about to release their first commercial product”, says Jonas.

“In game design you always want people to test and iterate and tell you how to make it better”, says Michael. We didn’t have a budget for testers. We didn’t have an office. So it was fantastic to have this huge community invested in BlindSide. It was the easiest play-testing experience I’ve had and we got tons of feedback. It was remarkable and really helpful”.

Jake and Tamas had about 30 people sign up as beta testers and “the feedback was extremely helpful”, says Jake. “We also sent out a monthly newsletter to our approximately 200 supporters, showing them some secret stuff and prototypes”, he says.“These were the folks connected to the game since its inception, so they talked about it and spread the word when it was released”.

As Jake sees it, supporters who act as evangelists for your work are as valuable as the money itself. He talks about a friend of his whose Kickstarter campaign failed to reach its funding goal, but who walked away with a huge community.

“We were hearing about Kickstarter exhaustion already when we launched our campaign”, says Jake. “I know the landscape has changed, but I think the platform is still there for folks doing small, realistically established projects. We were totally ecstatic. To us it was great that you could be a creator and decide for yourself what it means to be successful. And the support we got early on has been amazing for us and super helpful”.

Monologue

Monologue is a window into the world, work, and lives of the community members and developers that make up the Mono Project, which is a free cross-platform development environment used primarily on Linux.

If you would rather follow Monologue using a newsreader, we provide the following feed:

RSS 2.0 Feed

Monologue is powered by Mono and the Monologue software.

Bloggers