Adding Reorderable Lists in Unity

Often I find myself in need of reorderable list functionality in my various custom editor interfaces, and so I decided to create a generalised implementation which works with generic lists List<T> and with SerializedProperty.

Screenshot of Reorderable List Field

This list control provides drag and drop reordering and supports mixed item heights when using custom property drawers. It is generally better to present lists for serialized properties since Unity provides automatic undo/redo support for these. You can also implement your very own list adaptor to present entirely custom lists.

This control is provided as open source under the BSD license and can be downloaded from the following repository: https://bitbucket.org/rotorz/reorderable-list-editor-field-for-unity/overview

Continue reading

Advertisements

Automatic Initialisation at Runtime with Easy Maintenance!

Often when working with Unity I have the need to automatically initialise “controller” objects which live across scenes. In the past I have typically created an initialisation scene and used DontDestroyOnLoad. Whilst this works it makes debugging scenes a lot tricky since you cannot just hit the “Play” button.

It would be really great if Unity provided a runtime equivalent of InitializeOnLoad or better still a way to define scriptable objects which automatically spring into life when a certain runtime criteria is met (please vote here!).

I have been thinking of ways to circumvent this limitation and feel that I have come up with a pretty good solution. I would like to tip my hat to @Superpig for suggesting use of a ScriptableObject for game configuration.

Continue reading

Adding the little padlock button to your EditorWindow!

One of the less well known features of Unity is the little padlock button that lives in the upper-right corner of the Inspector window. This button is fantastic because it causes the inspector to ignore future selections and thus allowing you to select other objects without affecting the contents of the inspector.

Those who are needing (or just want the fancy little padlock!) to achieve a similar type of locking functionality in their own custom editor windows can simply by adding the magic method “ShowButton” to their editor window class. In fact, you don’t have to add a padlock, you could add some other icon!

Screenshot of custom editor window with lock icon.
Screenshot of custom editor window with lock icon.

Continue reading

Possibility of reusing custom editors in custom window?

This functionality has since been added in Unity 4!
See: http://docs.unity3d.com/Documentation/ScriptReference/Editor.CreateEditor.html

Several weeks ago I had some ideas that would add lots of flexibility to my custom editor window. In a nutshell the idea was to add, modify and remove certain components. To be honest I thought that this would be relatively easy because this functionality is already available within Unity inspector windows. I remembered seeing `EditorGUILayout.PropertyField` and I foolishly assumed that would do the trick, but I was wrong…

My next attempt was to enumerate component properties using `SerializedObject` and `SerializedProperty`. Whilst this approach did in fact provide something that resembled a custom inspector, it was extremely lacking. When I realised, this couldn’t possibly utilise custom editors!

For example, the `Transform` component has a custom inspector which is tailored specifically for it. In Rotorz Tile System we use a custom inspector on `RotorzTileSystem` components which allows properties to be modified and actions to be performed. These custom inspectors are easily defined using the `CustomEditor` attribute. So the idea here is to reuse these custom editors (which are not necessarily created by myself) within my editor window!

With thanks to MonoDevelop’s fantastic assembly browser I came across the undocumented class `UnityEditor.ActiveEditorTracker`. The publicly exposed methods are well named and fairly self-explanatory. So I had a go at creating a rough mockup of a custom inspector. I was pleasantly surprised at how easy this had now become. Creating a rudimentary custom inspector is as simple as shown below:

using UnityEngine;
using UnityEditor;

public class CustomWindow : EditorWindow {

    [MenuItem("Window/Test")]
    public static void Test() {
        EditorWindow.GetWindow<CustomWindow>("Test");
    }

    GameObject activeGO;
    Editor editor;

    void Update() {
        if (activeGO == Selection.activeGameObject)
            return;

        activeGO = Selection.activeGameObject;
        editor = null;

        if (activeGO != null)
            editor = UnityEditor.ActiveEditorTracker.MakeCustomEditor(activeGO.transform);

        Repaint();
    }

    void OnGUI() {
        GameObject go = Selection.activeGameObject;
        if (go == null)
            return;

        // Use the registered editor for `Transform`
        EditorGUILayout.InspectorTitlebar(true, editor.target);
        editor.OnInspectorGUI();
    }

}

Unfortunately this functionality is not currently documented and as such cannot be used in a commercial Unity extension because there is no guarantee that it will continue to work in future versions of Unity. This is a great shame because I could put this to good use! I also suspect that the developers of PlayMaker could utilise this functionality if it were documented for customisable action GUIs.

Please consider voting for Unity Technologies to add a basic level of documentation for this functionality 🙂
http://feedback.unity3d.com/unity/all-categories/1/hot/active/document-unityeditoractiveedi 

Changing data structure of MonoBehaviour in Unity Extension

Several customers who have purchased Rotorz Tile System have made a number of feature requests that exceed the original design of the product. I am delighted that my fellow game developers are finding Rotorz Tile System useful in their projects. There have been some fantastic suggestions which have already helped further the product.

Instead of hacking new features into the current design it seems more appropriate for the existing data structure to be updated. In addition to improving performance and reducing memory overhead it will make the new features easier to maintain.

Continue reading

Prepare 2D tile set for Rotorz Tile System [video]

I recently received a question asking if Rotorz Tile System could be used to paint 2D tiles. A tile is a three-dimensional object that is represented by a prefab. So the answer was yes, because a plane can be created and mapped to the tile texture. When working with tile sets it is generally a good idea to pack tiles into a texture atlas in order to keep the number of draw calls low.

The process of creating such tiles manually is not an overly complicated procedure, but can easily become time consuming. A plane mesh must be created for each texture atlas mapping with varying UVs for each tile. A tile brush must then be created for painting with. So I decided that it would be useful to add a utility window to ease the process of creating 2D tile brushes.

The following video demonstrates the process of creating a 2D tile set. The video then proceeds to demonstrate the creation of an oriented tile brush using the automatically generated tile brushes.

Credit for demo atlas artwork: http://mapledev.tumblr.com/post/10406905135/howtotileset

Continue reading

Developing extendable editor extensions for Unity 3D

Many of the editor extensions that are available from the asset store are closed source. For those who do not understand, this simply means that the source code is compiled into one or more class libraries (DLL).

There are a number of very good reasons why some extension developers choose to do this:

  • Avoid script naming conflicts with user code and indeed other extensions

    Unity requires that each script file that contains a MonoBehaviour is named to match the class name. Unity does not allow two user scripts to coexist with the same name; neither directories or namespaces will help here!

    However, these limitations do not apply to behaviours that are exposed by a class library. When developing a class library it is also possible to put namespaces to good use! This helps to avoid clashing with other extensions!

    Continue reading