50 tips for working with unity

Upload: kukuduxu

Post on 07-Jan-2016

25 views

Category:

Documents


1 download

DESCRIPTION

50 tips that will make you work better with Unity 3D

TRANSCRIPT

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 1/31

    devmag.org.zaA game development magazine

    50 Tips for Working with Unity (Best Practices)

    About these tips

    These tips are not all applicable to every project.

    They are based on my experience with projects with small teams from 3 to 20 people.

    Theres is a price for structure, re-usability, clarity, and so on team size and project size determine

    whether that price should be paid.

    Many tips are a matter of taste (there may be rivalling but equally good techniques for any tip

    listed here).

    Some tips may fly in the face of conventional Unity development. For instance, using prefabs for

    specialisation instead of instances is very non-Unity-like, and the price is quite high (many times

    more prefabs than without it). Yet I have seen these tips pay off, even if they seem crazy.

    Process

    1. Avoid branching assets. There should always only ever be one version of any asset. If you absolutely

    have to branch a prefab, scene, or mesh, follow a process that makes it very clear which is the right

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 2/31

    version. The wrong branch should have a funky name, for example, use a double underscore prefix:

    __MainScene_Backup. Branching prefabs requires a specific process to make it safe (see under the section

    Prefabs).

    2. Each team member should have a second copy of the project checked out for testing if you are

    using version control. After changes, this second copy, the clean copy, should be updated and tested. No-

    one should make any changes to their clean copies. This is especially useful to catch missing assets.

    3. Consider using external level tools for level editing. Unity is not the perfect level editor. For

    example, we have used TuDee to build levels for a 3D tile-based game, where we could benefit from the

    tile-friendly tools (snapping to grid, and multiple-of-90-degrees rotation, 2D view, quick tile selection).

    Instantiating prefabs from an XML file is straightforward. See Guerrilla Tool Development for more ideas.

    4. Consider saving levels in XML instead of in scenes. This is a wonderful technique:

    It makes it unnecessary to re-setup each scene.

    It makes loading much faster (if most objects are shared between scenes).

    It makes it easier to merge scenes (even with Unitys new text-based scenes there is so much data

    in there that merging is often impractical in any case).

    It makes it easier to keep track of data across levels.

    You can still use Unity as a level editor (although you need not). You will need to write some code to

    serialize and deserialize your data, and load a level both in the editor and at runtime, and save levels from

    the editor. You may also need to mimic Unitys ID system for maintaining references between objects.

    5. Consider writing generic custom inspector code. To write custom inspectors is fairly

    straightforward, but Unitys system has many drawbacks:

    It does not support taking advantage of inheritance.

    It does not let you define inspector components on a field-type level, only a class-type level. For

    instance, if every game object has a field of type SomeCoolType, which you want rendered

    differently in the inspector, you have to write inspectors for all your classes.

    You can address these issues by essentially re-implementing the inspector system. Using a few tricks of

    reflection, this is not as hard as it seems, details are provided at the end of the article.

    Scene Organisation

    6. Use named empty game objects as scene folders. Carefully organise your scenes to make it easy to

    find objects.

    7. Put maintenance prefabs and folders (empty game objects) at 0 0 0. If a transform is not

    specifically used to position an object, it should be at the origin. That way, there is less danger of running

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 3/31

    into problems with local and world space, and code is generally simpler.

    8. Minimise using offsets for GUI components. Offsets should always be used to layout components

    in their parent component only; they should not rely on the positioning of their grandparents. Offsets

    should not cancel each other out to display correctly. It is basically to prevent this kind of thing:

    Parent container arbitrarily placed at (100, -50). Child, meant to be positioned at (10, 10), then placed at

    (90, 60) [relative to parent].

    This error is common when the container is invisible, or does not have a visual representation at all.

    9. Put your world floor at y = 0. This makes it easier to put objects on the floor, and treat the world as a

    2D space (when appropriate) for game logic, AI, and physics.

    10. Make the game runnable from every scene. This drastically reduces testing time. To make all

    scenes runnable you need to do two things:

    First, provide a way to mock up any data that is required from previously loaded scenes if it is not

    available.

    Second, spawn objects that must persist between scene loads with the following idiom:

    myObject = FindMyObjectInScene();

    if (myObjet == null)

    {

    myObject = SpawnMyObject();

    }

    Art

    11. Put character and standing object pivots at the base, not in the centre. This makes it easy to

    put characters and objects on the floor precisely. It also makes it easier to work with 3D as if it is 2D for

    game logic, AI, and even physics when appropriate.

    12. Make all meshes face in the same direction (positive or negative z axis). This applies to meshes

    such as characters and other objects that have a concept of facing direction. Many algorithms are

    simplified if everything have the same facing direction.

    13. Get the scale right from the beginning. Make art so that they can all be imported at a scale factor

    of 1, and that their transforms can be scaled 1, 1, 1. Use a reference object (a Unity cube) to make scale

    comparisons easy. Choose a world to Unity units ratio suitable for your game, and stick to it.

    14. Make a two-poly plane to use for GUI components and manually created particles. Make the plane

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 4/31

    face the positive z-axis for easy billboarding and easy GUI building.

    15. Make and use test art

    Squares labelled for skyboxes.

    A grid.

    Various flat colours for shader testing: white, black, 50% grey, red, green, blue, magenta, yellow,

    cyan.

    Gradients for shader testing: black to white, red to green, red to blue, green to blue.

    Black and white checkerboard.

    Smooth and rugged normal maps.

    A lighting rig (as prefab) for quickly setting up test scenes.

    Prefabs

    16. Use prefabs for everything. The only game objects in your scene that should not be prefabs should

    be folders. Even unique objects that are used only once should be prefabs. This makes it easier to make

    changes that dont require the scene to change. (An additional benefit is that it makes building sprite

    atlases reliable when using EZGUI).

    17. Use separate prefabs for specialisation; do not specialise instances. If you have two enemy

    types, and they only differ by their properties, make separate prefabs for the properties, and link them in.

    This makes it possible to

    make changes to each type in one place

    make changes without having to change the scene.

    If you have too many enemy types, specialisation should still not be made in instances in the editor. One

    alternative is to do it procedurally, or using a central file / prefab for all enemies. A single drop down could

    be used to differentiate enemies, or an algorithm based on enemy position or player progress.

    18. Link prefabs to prefabs; do not link instances to instances. Links to prefabs are maintained

    when dropping a prefab into a scene; links to instances are not. Linking to prefabs whenever possible

    reduces scene setup, and reduce the need to change scenes.

    19. As far as possible, establish links between instances automatically. If you need to link

    instances, establish the links programmatically. For example, the player prefab can register itself with the

    GameManager when it starts, or the GameManager can find the Player prefab instance when it starts.

    Dont put meshes at the roots of prefabs if you want to add other scripts. When you make the

    prefab from a mesh, first parent the mesh to an empty game object, and make that the root. Put scripts

    on the root, not on the mesh node. That way it is much easier to replace the mesh with another mesh

    without loosing any values that you set up in the inspector.

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 5/31

    Use linked prefabs as an alternative to nested prefabs. Unity does not support nested prefabs, and

    existing third-party solutions can be dangerous when working in a team because the relationship

    between nested prefabs is not obvious.

    20. Use safe processes to branch prefabs. The explanation use the Player prefab as an example.

    Make a risky change to the Player prefab is as follows:

    1. Duplicate the Player prefab.

    2. Rename the duplicate to __Player_Backup.

    3. Make changes to the Player prefab.

    4. If everything works, delete __Player_Backup.

    Do not name the duplicate Player_New, and make changes to it!

    Some situations are more complicated. For example, a certain change may involve two people, and

    following the above process may break the working scene for everyone until person two finished. If it is

    quick enough, still follow the process above. For changes that take longer, the following process can be

    followed:

    1. Person 1:

    1. Duplicate the Player prefab.

    2. Rename it to __Player_WithNewFeature or __Player_ForPerson2.

    3. Make changes on the duplicate, and commit / give to Person 2.

    2. Person 2:

    1. Make changes to new prefab.

    2. Duplicate Player prefab, and call it __Player_Backup.

    3. Drag an instance of __Player_WithNewFeature into the scene.

    4. Drag the instance onto the original Player prefab.

    5. If everything works, delete __Player_Backup and __Player_WithNewFeature.

    Extensions and MonoBehaviourBase

    21. Extend your own base mono behaviour, and derive all your components from it.

    This allows you to implement some general functionality, such as type safe Invoke, and more

    complicated Invokes (such as random, etc.).

    22. Define safe methods for Invoke, StartCoroutine and Instantiate.

    Define a delegate Task, and use it to define methods that dont rely on string names. For example:

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 6/31

    public void Invoke(Task task, float time)

    {

    Invoke(task.Method.Name, time);

    }

    23. Use extensions to work with components that share an interface. It is sometimes convenient

    to get components that implement a certain interface, or find objects with such components.

    The implementations below uses typeof instead of the generic versions of these functions. The generic

    versions dont work with interfaces, but typeof does. The methods below wraps this neatly in generic

    methods.

    //Defined in the common base class for all mono behaviours

    public I GetInterfaceComponent() where I : class

    {

    return GetComponent(typeof(I)) as I;

    }

    public static List FindObjectsOfInterface() where I : class

    {

    MonoBehaviour[] monoBehaviours = FindObjectsOfType();

    List list = new List();

    foreach(MonoBehaviour behaviour in monoBehaviours)

    {

    I component = behaviour.GetComponent(typeof(I)) as I;

    if(component != null)

    {

    list.Add(component);

    }

    }

    return list;

    }

    24. Use extensions to make syntax more convenient. For example:

    public static class CSTransform

    {

    public static void SetX(this Transform transform, float x)

    {

    Vector3 newPosition =

    new Vector3(x, transform.position.y, transform.position.z);

    transform.position = newPosition;

    }

    ...

    }

    25. Use a defensive GetComponent alternative. Sometimes forcing component dependencies

    (through RequiredComponent) can be a pain. For example, it makes it difficult to change components in

    the inspector (even if they have the same base type). As an alternative, the following extension of

    GameObject can be used when a component is required to print out an error message when it is not

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 7/31

    found.

    public static T GetSafeComponent(this GameObject obj) where T : MonoBehaviour

    {

    T component = obj.GetComponent();

    if(component == null)

    {

    Debug.LogError("Expected to find component of type "

    + typeof(T) + " but found none", obj);

    }

    return component;

    }

    Idioms

    26. Avoid using different idioms to do the same thing. In many cases there are more than one

    idiomatic way to do things. In such cases, choose one to use throughout the project. Here is why:

    Some idioms dont work well together. Using one idiom well forces design in one direction that is

    not suitable for another idiom.

    Using the same idiom throughout makes it easier for team members to understand what is going

    on. It makes structure and code easier to understand. It makes mistakes harder to make.

    Examples of idiom groups:

    Coroutines vs. state machines.

    Nested prefabs vs. linked prefabs vs. God prefabs.

    Data separation strategies.

    Ways of using sprites for states in 2D games.

    Prefab structure.

    Spawning strategies.

    Ways to locate objects: by type vs. name vs. tag vs. layer vs. reference (links).

    Ways to group objects: by type vs. name vs. tag vs. layer vs. arrays of references (links).

    Finding groups of objects versus self registration.

    Controlling execution order (Using Unitys execution order setup versus yield logic versus Awake /

    Start and Update / Late Update reliance versus manual methods versus any-order architecture).

    Selecting objects / positions / targets with the mouse in-game: selection manager versus local self-

    management.

    Keeping data between scene changes: through PlayerPrefs, or objects that are not Destroyed when

    a new scene is loaded.

    Ways of combining (blending, adding and layering) animation.

    Time

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 8/31

    27. Maintain your own time class to make pausing easier. Wrap Time.DeltaTime and

    Time.TimeSinceLevelLoad to account for pausing and time scale. It requires discipline to use it, but will

    make things a lot easier, especially when running things of different clocks (such as interface animations

    and game animations).

    Spawning Objects

    28. Dont let spawned objects clutter your hierarchy when the game runs. Set their parents to a

    scene object to make it easier to find stuff when the game is running. You could use a empty game object,

    or even a singleton with no behaviour to make it easier to access from code. Call this object

    DynamicObjects.

    Class Design

    29. Use singletons for convenience. The following class will make any class that inherits from it a

    singleton automatically:

    public class Singleton : MonoBehaviour where T : MonoBehaviour

    {

    protected static T instance;

    /**

    Returns the instance of this singleton.

    */

    public static T Instance

    {

    get

    {

    if(instance == null)

    {

    instance = (T) FindObjectOfType(typeof(T));

    if (instance == null)

    {

    Debug.LogError("An instance of " + typeof(T) +

    " is needed in the scene, but there is none.");

    }

    }

    return instance;

    }

    }

    }

    Singletons are useful for managers, such as ParticleManager or AudioManager or GUIManager.

    Avoid using singletons for unique instances of prefabs that are not managers (such as the Player).

    Not adhering to this principle complicates inheritance hierarchies, and makes certain types of

    changes harder. Rather keep references to these in your GameManager (or other suitable God class

    )

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 9/31

    Define static properties and methods for public variables and methods that are used often from

    outside the class. This allows you to write GameManager.Player instead of

    GameManager.Instance.player.

    30. For components, never make variables public that should not be tweaked in the inspector.

    Otherwise it will be tweaked by a designer, especially if it is not clear what it does. In some rare cases it is

    unavoidable. In that case use a two or even four underscores to prefix the variable name to scare away

    tweakers:

    public float __aVariable;

    31. Separate interface from game logic. This is essentially the MVC pattern.

    Any input controller should only give commands to the appropriate components to let them know the

    controller has been invoked. For example in controller logic, the controller could decide which commands

    to give based on the player state. But this is bad (for example, it will lead to duplicate logic if more

    controllers are added). Instead, the Player object should be notified of the intent of moving forward, and

    then based on the current state (slowed or stunned, for example) set the speed and update the player

    facing direction. Controllers should only do things that relate to their own state (the controller does not

    change state if the player changes state; therefore, the controller should not know of the player state at

    all). Another example is the changing of weapons. The right way to do it is with a method on Player

    SwitchWeapon(Weapon newWeapon), which the GUI can call. The GUI should not manipulate transforms

    and parents and all that stuff.

    Any interface component should only maintain data and do processing related to its own state. For example,

    do display a map, the GUI could compute what to display based on the players movements. However,

    this is game state data, and does not belong in the GUI. The GUI should merely display game state data,

    which should be maintained elsewhere. The map data should be maintained elsewhere (in the

    GameManager, for example).

    Gameplay objects should know virtually nothing of the GUI. The one exception is the pause behaviour,

    which is may be controlled globally through Time.timeScale (which is not a good idea as well see ).

    Gameplay objects should know if the game is paused. But that is all. Therefore, no links to GUI

    components from gameplay objects.

    In general, if you delete all the GUI classes, the game should still compile.

    You should also be able to re-implement the GUI and input without needing to write any new game logic.

    32. Separate state and bookkeeping. Bookkeeping variables are used for speed or convenience, and

    can be recovered from the state. By separating these, you make it easier to

    save the game state, and

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 10/31

    debug the game state.

    One way to do it is to define a SaveData class for each game logic class. The

    [Serializable]

    PlayerSaveData

    {

    public float health; //public for serialisation, not exposed in inspector

    }

    Player

    {

    //... bookkeeping variables

    //Dont expose state in inspector. State is not tweakable.

    private PlayerSaveData playerSaveData;

    }

    33. Separate specialisation configuration.

    Consider two enemies with identical meshes, but different tweakables (for instance different strengths

    and different speeds). There are different ways to separate data. The one here is what I prefer, especially

    when objects are spawned, or the game is saved. (Tweakables are not state data, but configuration data,

    so it need not be saved. When objects are loaded or spawned, the tweakables are automatically loaded in

    separately)

    Define a template class for each game logic class. For instance, for Enemy, we also define

    EnemyTemplate. All the differentiating tweakables are stored in EnemyTemplate

    In the game logic class, define a variable of the template type.

    Make an Enemy prefab, and two template prefabs WeakEnemyTemplate and StrongEnemyTemplate.

    When loading or spawning objects, set the template variable to the right template.

    This method can become quite sophisticated (and sometimes, needlessly complicated, so beware!).

    For example, to better make use of generic polymorphism, we may define our classes like this:

    public class BaseTemplate

    {

    ...

    }

    public class ActorTemplate : BaseTemplate

    {

    ...

    }

    public class Entity where EntityTemplateType : BaseTemplate

    {

    EntityTemplateType template;

    ...

    }

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 11/31

    public class Actor : Entity

    {

    ...

    }

    34. Dont use strings for anything other than displayed text. In particular, do not use strings for

    identifying objects or prefabs etc. One unfortunate exception is animations, which generally are accessed

    with their string names.

    35. Avoid using public index-coupled arrays. For instance, do not define an array of weapons, an array

    of bullets, and an array of particles , so that your code looks like this:

    public void SelectWeapon(int index)

    {

    currentWeaponIndex = index;

    Player.SwitchWeapon(weapons[currentWeapon]);

    }

    public void Shoot()

    {

    Fire(bullets[currentWeapon]);

    FireParticles(particles[currentWeapon]);

    }

    The problem for this is not so much in the code, but rather setting it up in the inspector without making

    mistakes.

    Rather, define a class that encapsulates the three variables, and make an array of that:

    [Serializable]

    public class Weapon

    {

    public GameObject prefab;

    public ParticleSystem particles;

    public Bullet bullet;

    }

    The code looks neater, but most importantly, it is harder to make mistakes in setting up the data in the

    inspector.

    36. Avoid using arrays for structure other than sequences. For example, a player may have three

    types of attacks. Each uses the current weapon, but generates different bullets and different behaviour.

    You may be tempted to dump the three bullets in an array, and then use this kind of logic:

    public void FireAttack()

    {

    /// behaviour

    Fire(bullets[0]);

    }

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 12/31

    public void IceAttack()

    {

    /// behaviour

    Fire(bullets[1]);

    }

    public void WindAttack()

    {

    /// behaviour

    Fire(bullets[2]);

    }

    Enums can make things look better in code

    public void WindAttack()

    {

    /// behaviour

    Fire(bullets[WeaponType.Wind]);

    }

    but not in the inspector.

    Its better to use separate variables so that the names help show which content to put in. Use a class to

    make it neat.

    [Serializable]

    public class Bullets

    {

    public Bullet FireBullet;

    public Bullet IceBullet;

    public Bullet WindBullet;

    }

    This assumes there is no other Fire, Ice and Wind data.

    37. Group data in serializable classes to make things neater in the inspector. Some entities may

    have dozens of tweakables. It can become a nightmare to find the right variable in the inspector. To make

    things easier, follow these steps:

    Define separate classes for groups of variables. Make them public and serializable.

    In the primary class, define public variables of each type defined as above.

    Do not initialize these variables in Awake or Start; since they are serializable, Unity will take care of

    that.

    You can specify defaults as before by assigning values in the definition;

    This will group variables in collapsible units in the inspector, which is easier to manage.

    [Serializable]

    public class MovementProperties //Not a MonoBehaviour!

    {

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 13/31

    public float movementSpeed;

    public float turnSpeed = 1; //default provided

    }

    public class HealthProperties //Not a MonoBehaviour!

    {

    public float maxHealth;

    public float regenerationRate;

    }

    public class Player : MonoBehaviour

    {

    public MovementProperties movementProeprties;

    public HealthPorperties healthProeprties;

    }

    Text

    38. If you have a lot of story text, put it in a file. Dont put it in fields for editing in the inspector. Make

    it easy to change without having to open the Unity editor, and especially without having to save the

    scene.

    39. If you plan to localise, separate all your strings to one location. There are many ways to do this.

    One way is to define a Text class with a public string field for each string, with defaults set to English, for

    example. Other languages subclass this and re-initialize the fields with the language equivalents.

    More sophisticated techniques (appropriate when the body of text is large and / or the number of

    languages is high) will read in a spread sheet and provide logic for selecting the right string based on the

    chosen language.

    Testing and Debugging

    40. Implement a graphical logger to debug physics, animation, and AI. This can make debugging

    considerably faster. See here.

    41. Implement a HTML logger. In some cases, logging can still be useful. Having logs that are easier to

    parse (are colour coded, has multiple views, records screenshots) can make log-debugging much more

    pleasant. See here.

    42. Implement your own FPS counter. Yup. No one knows what Unitys FPS counter really measures,

    but it is not frame rate. Implement your own so that the number can correspond with intuition and

    visual inspection.

    43. Implement shortcuts for taking screen shots. Many bugs are visual, and are much easier to

    report when you can take a picture. The ideal system should maintain a counter in PlayerPrefs so that

    successive screenshots are not overwritten. The screenshots should be saved outside the project folder

    to avoid people from accidentally committing them to the repository.

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 14/31

    44. Implement shortcuts for printing the players world position. This makes it easy to report the

    position of bugs that occur in specific places in the world, which in turns makes it easier to debug.

    45. Implement debug options for making testing easier. Some examples:

    Unlock all items.

    Disable enemies.

    Disable GUI.

    Make player invincible.

    Disable all gameplay.

    46. For teams that are small enough, make a prefab for each team member with debug options.

    Put a user identifier in a file that is not committed, and is read when the game is run. This why:

    Team members do not commit their debug options by accident and affect everyone.

    Changing debug options dont change the scene.

    47. Maintain a scene with all gameplay elements. For instance, a scene with all enemies, all objects

    you can interact with, etc. This makes it easy to test functionality without having to play too long.

    48. Define constants for debug shortcut keys, and keep them in one place. Debug keys are not

    normally (or conveniently) processed in a single location like the rest of the game input. To avoid shortcut

    key collisions, define constants in a central place. An alternative is to process all keys in one place

    regardless of whether it is a debug function or not. (The downside is that this class may need extra

    references to objects just for this).

    Documentation

    49. Document your setup. Most documentation should be in the code, but certain things should be

    documented outside code. Making designers sift through code for setup is time-wasting. Documented

    setups improved efficiency (if the documents are current).

    Document the following:

    Layer uses (for collision, culling, and raycasting essentially, what should be in what layer).

    Tag uses.

    GUI depths for layers (what should display over what).

    Scene setup.

    Idiom preferences.

    Prefab structure.

    Animation layers.

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 15/31

    Naming Standard and Folder Structure

    50. Follow a documented naming convention and folder structure. Consistent naming and folder

    structure makes it easier to find things, and to figure out what things are.

    You will most probably want to create your own naming convention and folder structure. Here is one as

    an example.

    Naming General Principles

    1. Call a thing what it is. A bird should be called Bird.

    2. Choose names that can be pronounced and remembered. If you make a Mayan game, do not

    name your level QuetzalcoatisReturn.

    3. Be consistent. When you choose a name, stick to it.

    4. Use Pascal case, like this: ComplicatedVerySpecificObject. Do not use spaces, underscores, or

    hyphens, with one exception (see Naming Different Aspects of the Same Thing).

    5. Do not use version numbers, or words to indicate their progress (WIP, final).

    6. Do not use abbreviations: DVamp@W should be DarkVampire@Walk.

    7. Use the terminology in the design document: if the document calls the die animation Die, then use

    DarkVampire@Die, not DarkVampire@Death.

    8. Keep the most specific descriptor on the left: DarkVampire, not VampireDark; PauseButton, not

    ButtonPaused. It is, for instance, easier to find the pause button in the inspector if not all buttons

    start with the word Button. [Many people prefer it the other way around, because that makes

    grouping more obvious visually. Names are not for grouping though, folders are. Names are to

    distinguish objects of the same type so that they can be located reliably and fast.]

    9. Some names form a sequence. Use numbers in these names, for example, PathNode0, PathNode1.

    Always start with 0, not 1.

    10. Do not use numbers for things that dont form a sequence. For example, Bird0, Bird1, Bird2 should

    be Flamingo, Eagle, Swallow.

    11. Prefix temporary objects with a double underscore __Player_Backup.

    Naming Different Aspects of the Same Thing

    Use underscores between the core name, and the thing that describes the aspect. For instance:

    GUI buttons states EnterButton_Active, EnterButton_Inactive

    Textures DarkVampire_Diffuse, DarkVampire_Normalmap

    Skybox JungleSky_Top, JungleSky_North

    LOD Groups DarkVampire_LOD0, DarkVampire_LOD1

    Do not use this convention just to distinguish between different types of items, for instance Rock_Small,

    Rock_Large should be SmallRock, LargeRock.

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 16/31

    Structure

    The organisation of your scenes, project folder, and script folder should follow a similar pattern.

    Folder Structure

    Materials

    GUI

    Effects

    Meshes

    Actors

    DarkVampire

    LightVampire

    ...

    Structures

    Buildings

    ...

    Props

    Plants

    ...

    ...

    Plugins

    Prefabs

    Actors

    Items

    ...

    Resources

    Actors

    Items

    ...

    Scenes

    GUI

    Levels

    TestScenes

    Scripts

    Textures

    GUI

    Effects

    ...

    Scene Structure

    Cameras

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 17/31

    Dynamic Objects

    Gameplay

    Actors

    Items

    ...

    GUI

    HUD

    PauseMenu

    ...

    Management

    Lights

    World

    Ground

    Props

    Structure

    ...

    Scripts Folder Structure

    ThirdParty

    ...

    MyGenericScripts

    Debug

    Extensions

    Framework

    Graphics

    IO

    Math

    ...

    MyGameScripts

    Debug

    Gameplay

    Actors

    Items

    ...

    Framework

    Graphics

    GUI

    ...

    How to Re-implement Inspector Drawing

    1. Define a base class for all your editors

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 18/31

    BaseEditor : Editor

    where T : MonoBehaviour

    {

    override public void OnInspectorGUI()

    {

    T data = (T) target;

    GUIContent label = new GUIContent();

    label.text = "Properties"; //

    DrawDefaultInspectors(label, data);

    if(GUI.changed)

    {

    EditorUtility.SetDirty(target);

    }

    }

    }

    2. Use reflection and recursion to do draw components

    public static void DrawDefaultInspectors(GUIContent label, T target)

    where T : new()

    {

    EditorGUILayout.Separator();

    Type type = typeof(T);

    FieldInfo[] fields = type.GetFields();

    EditorGUI.indentLevel++;

    foreach(FieldInfo field in fields)

    {

    if(field.IsPublic)

    {

    if(field.FieldType == typeof(int))

    {

    field.SetValue(target, EditorGUILayout.IntField(

    MakeLabel(field), (int) field.GetValue(target)));

    }

    else if(field.FieldType == typeof(float))

    {

    field.SetValue(target, EditorGUILayout.FloatField(

    MakeLabel(field), (float) field.GetValue(target)));

    }

    ///etc. for other primitive types

    else if(field.FieldType.IsClass)

    {

    Type[] parmTypes = new Type[]{ field.FieldType};

    string methodName = "DrawDefaultInspectors";

    MethodInfo drawMethod =

    typeof(CSEditorGUILayout).GetMethod(methodName);

    if(drawMethod == null)

    {

    Debug.LogError("No method found: " + methodName);

    }

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 19/31

    bool foldOut = true;

    drawMethod.MakeGenericMethod(parmTypes).Invoke(null,

    new object[]

    {

    MakeLabel(field),

    field.GetValue(target)

    });

    }

    else

    {

    Debug.LogError(

    "DrawDefaultInspectors does not support fields of type " +

    field.FieldType);

    }

    }

    }

    EditorGUI.indentLevel--;

    }

    The above method uses the following helper:

    private static GUIContent MakeLabel(FieldInfo field)

    {

    GUIContent guiContent = new GUIContent();

    guiContent.text = field.Name.SplitCamelCase();

    object[] descriptions =

    field.GetCustomAttributes(typeof(DescriptionAttribute), true);

    if(descriptions.Length > 0)

    {

    //just use the first one.

    guiContent.tooltip =

    (descriptions[0] as DescriptionAttribute).Description;

    }

    return guiContent;

    }

    Note that it uses an annotation in your class code to generate a tooltip in the inspector.

    3. Define new Custom Editors

    Unfortunately, you will still need to define a class for each MonoBehaviour. Fortunately, these definitions

    can be empty; all the actual work is done by the base class.

    [CustomEditor(typeof(MyClass))]

    public class MyClassEditor : BaseEditor

    {}

    In theory this step can be automated, but I have not tried it.

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 20/31

    TweetTweet 343 Me gusta 537

    130

    No related posts.

    This entry was posted in Development and tagged best practices, unity on 12 July 2012

    [http://devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/] by Herman Tulleken.

    About Herman Tulleken

    Herman Tulleken is a freelance game developer and a toolmaker. He sees computers as a necesary evil to

    make cool games, and likes to torture the bitbrains with cool tools. He really wants to run the world, but

    for now, the only thing he runs is this site. [Articles]

    View all posts by Herman Tulleken

    76 comments

    Leave a message...

    BestBest CommunityCommunity ShareShare

    Reply

    David Goemans 2 months ago

    Great list!

    Just a pointer for #30:

    If you have public variables, but don't want them accessible in the inspector, you can

    add [HideInInspector] ( C# ) or @HideInInspector (JS) before the declaration.

    Conversely, if you want variables to be set in the inspector, but invisible in public scope,

    you can add [SerializeField] (C#) or @SerializeField.

    5

    Tim a year ago

    This is probably the best Unity "tips" article I've ever read. Very informative! I came up

    with a few questions while I was reading and was wondering if Herman, or any one else

    had any comments/answers to my questions.

    #4 - Any example projects, code examples, or direction on how to acheive this?

    9

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 21/31

    Reply

    #26 - "Coroutines vs. state machines." Are you saying use Coroutines or State

    Machines, but not both? Or, Deciding if you are going to create state machines through

    the use of coroutines or if you are going to create state machines by some other

    method?

    In addition to #26. I'm really struggling trying to decide how I want manage state. I've

    seen several good FSMs and then there are some who say don't both, just use

    coroutines. Then I've seen a hybrid of both. Any thoughts/tips on this, or examples of

    how you manage state on an object?

    #27 I understand what you are trying to achieve and why, but I don't understand how

    you are explaining to do it. Could I get a short example of how you are wrapping

    Time.DeltaTime and Time.SinceLevelLoad?

    #34 says "Dont use strings for anything other than displayed text". Do you not use

    Tags at all? Aren't strings the only way to reference tags/layers through code?

    Any feedback is greatly appreciated, Thanks!

    3

    Reply

    see more

    Herman Tulleken a year ago Tim

    Thanks Tim!

    About #4. It's quite a big chunk of code. I will see and post some if it at some

    stage. The basic idea is to split off data that needs to be saved into Serializable

    classes, implement a common interface for Savable classes (that includes pre-

    saving and post-loading logic, for example, to copy transforms), then implement

    methods that serialize and deserialize lists of your Savable objects [and do the

    stuff necessary to link this data up to the actual game objects] (including

    instantiating assets from Resources), and a method to clear Savables from the

    scene. The save and load needs to work both run time and edit time. It is easier

    to start getting things work runtime, and then specialize behaviour for edit time

    (so reducing the risk of stuffing up scenes).

    All in all, not worth it if your levels are simple, and you only have a few. It also

    requires very clear thinking, otherwise everything can become real messy.

    #26. Yes, deciding to use co-routines for states, vs a nice wrapped solution. We

    use light weight state machines that transition on command; each object

    maintains it's own. The main reason not to mix these (or other idioms on the

    1

    Tim a year ago Herman Tulleken

    Thanks for all the great information! You said " We use light weight state

    machines that transition on command" could you give a quick snippet of

    how your state machines work? Since there are endless ways to do

    state machines I would like to see one that someone has/is using within

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 22/31

    Reply

    Unity. Thanks again for all the great information.

    Reply

    Barrie Treloar 4 months ago

    Can you elaborate on point "34. Dont use strings for anything other than displayed text."

    What should use for identifying objects?

    2

    Reply

    weezz 2 months ago Barrie Treloar

    .Net strings allocate memory each time you instance them or modify them

    Reply

    Iowaska 2 months ago Barrie Treloar

    I like to use GUIDs

    Reply

    Bruno 3 months ago

    Tip number 30:

    [System.NonSerialized]

    public float __aVariable;

    this makes the variable not to appear on the editor even if it is public.

    1

    Reply

    Amir Abiri 8 months ago

    RE 46 - you can use PlayerPrefs with a custom inspector on a dummy

    ScriptableObject. That way debug settings are stored in user data (registry / user home

    dir) and there is no need to have multiple or user-named objects and mess around with

    Subversion ignores for those objects.

    1

    Chris Amyot 10 months ago

    First of all - thank you for this GREAT article. I've been using the pattern you've

    described in #'s 32 and 37, using serializable non-monobehavior classes to

    encapsulate groups of variables. I'm relatively new to C#, so you kind of blew my mind

    there.

    While using this technique in Unity, I came to a stumbling block - copy/pasting the code

    from either of those examples provided the error:

    "Assets/Scripts/TestClass.cs(9,2): error CS0246: The type or namespace name

    `Serializable' could not be found. Are you missing a using directive or an assembly

    reference?"

    The fix I found for this is to use [System.Serializable] instead of [Serializable] - not sure

    if there's a better way of doing this..?

    Also - it's worth noting that you must include the [System.Serializable] attribute above

    Share

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 23/31

    Reply

    Also - it's worth noting that you must include the [System.Serializable] attribute above

    any class declaration that you want to show up in your inspector.

    Thanks again Herman - this is exactly the kind of resource I'd been looking for!

    1

    Reply

    Chris Amyot 10 months ago Chris Amyot

    Actually - just realized that if I included "using System;" at the top of my CS file I

    could use [Serializable] instead of [System.Serializable]. It seems to me (as a

    newcomer to C#), that including the System namespace in your classes would

    bring in a lot of unnecessary functionality.. Is this not the case? Is the compiler

    smart enough to include only the required functionality from that namespace?

    3

    Reply

    Amir Abiri 8 months ago Chris Amyot

    There is absolutely no penalty for including a namespace, it's just not

    how the C# language works. The using directive only helps the compiler

    resolve type names that appear in the code file, nothing more. It's just a

    way to narrow down the search and avoid ambiguity.

    During compilation, these references to other types are resolved and

    enter in their fully qualified form into the resulting bytecode. From there

    on the using directive is meaningless. The only thing that matters is

    which assemblies the compiled code needs to pull in or reference.

    In that respect there is no difference between "using System" or

    "System.Serializable", in both cases the code requires a reference to the

    assembly that contains the System.Serializable class, irrespective of

    what else the using directives may contain.

    Reply

    Farrell 14 days ago

    This is awesome. I'm a veteran game developer, but new to Unity. There were some

    really nice tips.

    am 25 days ago

    Could you provide an example for point 31? I think there is some tight coupling in Unity

    that makes modifying state of an object update it on screen automatically. Especially

    when using physics. In your example where you modify the player velocity, if you do that

    on a rigidbody in unity you'll move the object. Or do you mean that you should have:

    controller - code which calls something like Input.GetAxis and then calls a method on

    the model/game logic. i.e. like Move(Vector3 inputDirection).

    model/game logic - updates the player direction and velocity in the model class, but

    doesn't touch the rigidBody or anything to actually move it. Then using some sort of

    event manager possibly send out a notification message for this?

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 24/31

    Reply

    see more

    view/interface : Looks up the new velocity from the model code and just modifies the

    physics velocity on the rigid body. Also may change the direction sprite or rotation of the

    3d model?

    Would you typically make this in one monobehavior script? Or multiple?

    There is a logical order that things must happen.

    Get the input - A MonoBehaviour class which gets the input

    Reply

    elBlogDePier a month ago

    Write a book godammit! All Unity books are for beginners...

    Reply

    Samuel Asher Rivello 2 months ago

    FANTASTIC Overview. So when we open a new project and import any Unity

    Technologies package and the only folder organization enforced is an 'Assets' folder

    with a subfolder of 'Standard Assets'. What about our custom assets?

    Here is the SOLUTION. What Unity Folder Structure Do you Use? - http://bit.ly/1b7cLyq

    -Sam!

    Reply

    thakk 3 months ago

    VampireDark is better than DarkVampire. I want all my VampireX mobs to appear

    together, not spread all over the goddamn list.

    Reply

    Mario Azevedo 2 months ago thakk

    As he said, you should use a folder for that.

    Reply

    Charles InCharge 2 months ago Mario Azevedo

    It is more of a problem when debugging in the scene view. Lets say you

    put all your spawns in a spawns folder so you don't clutter the hierarchy.

    If you call them "DarkVampire" and "MrVampire", then your vampires are

    going to be all over the list. You could add a logic code to your spawning

    code though and have it create the empty game object folders at run

    time. That way your scene view would have "Spawns\Vampires\

    [Dark,Mr]". You could then put all that in an #if UNITY_EDITOR block so

    your performance isn't even remotely hit.

    1

    devmag a month agoM o d CharlesInCharge

    I normally use empty game objects liberally to organise my

    Share

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 25/31

    Reply

    I normally use empty game objects liberally to organise my

    scene as well. I would typically root all my vampires to a game

    object (named Vampires) if I find it's a problem. And of course

    the search box is very handy for finding vampires (however they

    are named). So yes, the rule works well in my workflow and

    structure. If it does not for you, ditch it :)

    Reply

    Amilia Jones 3 months ago

    This article is great, but the part I was most excited about is the part with which I'm

    having the most difficulty. The code in "How to Re-implement Inspector Drawing" looks

    great, but I'm not sure how to actually set this up in a cs file. I've tried, but I get many

    errors no matter what I seem to do.

    Reply

    Flavio 3 months ago

    Very useful article! thanks for that!

    Reply

    D 4 months ago

    Bookmarked so hard. I am completely new to Unity but far from new in Game

    development in general. This is just the type of guide I needed to get started. Thank you

    so very much!

    If I had a suggestion for an improvement I would recommend putting in a single

    sentence for all the folders in the folder structure detailing what they contain. But I bet

    it's obvious if you have been using Unity for any period of time.

    Reply

    caue 4 months ago

    I'm not sure I follow what you mean on steps 1, 2 and 30.

    1. By "branch" you mean just having an asset backup copy outside of the repository? If

    so, I completely agree - this should never be done.

    2. By second copy, you basically mean having the whole project with its compiled

    library at hand? That makes a lot of sense, but then why not also enforcing the

    repository usage on the rule? I don't see why that's not included.

    30. Why not simply using [System.NonSerialized] to hide public parameters from the

    inspector?

    Additionally, I'd advice using POedit for dealing with text languages, on the tip #39:

    http://wiki.unity3d.com/index....

    Fucking awesome list, by the way. Kinda sad it's good being that big... Hope Unity can

    "fix" most of it soon enough, though I couldn't bother taking note of how many here are

    things Unity could "fix". :-)

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 26/31

    Reply

    Reply

    devmag a month agoM o d caue

    1. By branch I mean making any duplicate that is not the *actual working* one

    (not made through a formal version controlled branching process). This occurs

    frequently when programmers or artists work on complicated prefabs or

    gameObjects and are scared that they will break something. Although not-

    breaking-anything is a noble pursuit, the wrong version almost *always* come

    and confuse the hell out of somebody, wasting many hours.

    2. Yup, that is what I mean. On some projects version control is not used, in

    which case the rule does not apply. (I don't recommend going without version

    control of course).

    30. Yes, the "on a rare occasion" part of that rule is really rare (I have not had

    the need for it for over a year now). I like the extremely ugly name for something

    that is also extremely ugly in itself. For me, a public variable _means_ it is a

    tweakable. So if I am not in the class, I treat it as something that should not be

    modified. The double underscore signifies something fishy is going on, and puts

    the programmer on alert. Of course, if for you public means public in the

    traditional sense, then simply using the annotation is perfectly fine. In either

    event, it really should be very rare, and is in itself not so important compared to

    the main part of the rule.

    39. Thanks for the suggestion. I admit the solution I give is a bit poor-man-style.

    Thanks for the feedback; it's very interesting to hear other's take on these

    points.

    1

    Reply

    caue a month ago devmag

    Thank you for the post! I'm trying to apply several of the rules here and

    the prefabbing scene one helped a great deal already, for merging

    scenes.

    I just think you should enforce way more the "use version control" idea.

    Even for 1 person minor projects free unity, just never go without a VCS.

    I see both rules #1 and #2 exist because people aren't using it or are

    using it poorly.

    Reply

    devmag a month agoM o d caue

    Yes I agree. Especially rule #1 is broken most often because of

    lack in faith in the versioning system, or lack in faith in his/her

    own capabilities to use it. Rule #2 is similarly to compensate for

    poor commitment practices.

    Matt Schoen a month ago caue

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 27/31

    Reply

    Matt Schoen a month ago caue

    We've actually just created a tool for this purpose and released it on the Asset

    Store. Check it out:

    https://www.assetstore.unity3d...

    Reply

    caue a month ago Matt Schoen

    That sounds unreal! And seems like it even works with git!

    I hate the Asset Server, and I advice no one to ever use it (in its current

    form anyway). It's basically older than svn in terms of version control.

    Just saying that because you do mention it twice on the documentation,

    and seems like there is an issue with scene missing references and ID

    mismatches in which you say AssetServer might be needed... No idea

    what you meant there, but that might be because I haven't tried your tool.

    The way I see it, a missing reference is missing. There's nothind to be

    done there. Just report it's missing.

    Reply

    Rohit 4 months ago

    I found your tips very interesting. I have a problem. I made an object in Maya and

    imported it into unity but the movement speed on device while testing is very slow. Can

    you please tell me that whether is it fault with some maya fbx file or in Unity? I spent 2

    days on this and reached nowhere. Please help. (Maya file is an office view)

    Reply

    Thomas 5 months ago

    Hey all,

    I'm not able to recreate the steps from "How to Re-implement Inspector Drawing" into

    final cs files. Could someone share that final or near work?

    Thanks for this article !

    Bye

    Reply

    Matt Schoen a month ago Thomas

    This is a bit of a complicated answer (which I won't go into too deeply), but you

    should look into SerializedProperty. Once you get a hang of the iterator pattern,

    it makes re-creating the inspector a breeze!

    Whitebread 5 months ago

    I know this is a bit old at this point, but I had a question in regards to the MakeLabel

    function. I am getting an error on field.Name.SplitCamelCase() saying that string does

    not contain a definition for it. Is this defined somewhere else?

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 28/31

    Reply

    not contain a definition for it. Is this defined somewhere else?

    Reply

    Jacob 7 months ago

    Just want to say thanks for this great article! so - thanks! :)

    Reply

    thall ippoli 8 months ago

    Thank you for this wonderful collection - it's a great reference!

    About Item #29,

    public class Singleton : MonoBehaviour where T : MonoBehaviour

    wouldn't this line work equally well as

    public class Singleton< T > : MonoBehaviour where T : class

    I'm trying to understand why you used "where T : MonoBehaviour"

    because in my mind that looks redundant - as I understand, the expected usage would

    be like this

    public class World : Singleton< World >

    Your code does work without any hitches though :)

    Reply

    devmag 8 months agoM o d thallippoli

    If you specify "where T : Monobehaviour", you can take advantage of

    Monobehavior methods in your singleton class if you needed to add more

    functionality.

    If you use your specification, this for example, would be illegal:

    if(instance == null)

    {

    instance = (T) FindObjectOfType(typeof(T));

    instance.transform.position = Vector3.zeo; //would be illegal

    if (instance == null)

    {

    Debug.LogError("An instance of " + typeof(T) +

    " is needed in the scene, but there is none.");

    }

    }

    1

    thall ippoli 8 months ago devmag

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 29/31

    Reply

    Got it, thanks!

    Reply

    shachar Oz 9 months ago

    excellent.

    our team at Omek has learned not a few out of the 50 you wrote, so these tips are fully

    supported by us too.

    Reply

    shinriyo 11 months ago

    Hi. I have just a question.

    How do you use Singleton class?

    I think it can't attach to GameObject. it must be instance and assign some object to this

    Instance property?

    Singleton singleton = new Singleton();

    singleton.Instance = hogeObject;

    Reply

    caue 2 months ago shinriyo

    As reference for one way this could be done, and while not sure if this would be

    a best practice, I've changed the singleton implementation for myself so we

    don't need to manually attach it to an object (same way as DebugConsole

    works). Here's just the part changed:

    if (_instance == null)

    {

    GameObject singleton = new GameObject();

    singleton.AddComponent();

    singleton.name = "(singleton) "+ typeof(T).ToString();

    DontDestroyOnLoad(singleton);

    _instance = FindObjectOfType( typeof(T) ) as T;

    Debug.Log("[Singleton] An instance of " + typeof(T) +

    " is needed in the scene, so '" + singleton +

    "' was created.");

    }

    Reply

    shinriyo 11 months ago shinriyo

    Ah..I see. If we attach Component to someobject. it automatically works, doesn't

    it?

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 30/31

    Reply

    shinriyo 11 months ago

    The source code of #23

    I guess it can't be compiled. Because it return object type.

    MonoBehaviour[] monoBehaviours = FindObjectsOfType();

    I fixed below and it can be compiled.

    MonoBehaviour[] monoBehaviours = FindObjectsOfType(typeof(MonoBehaviour)) as

    MonoBehaviour[];

    Reply

    Tim Aidley 11 months ago

    Re #30, is there any reason why you wouldn't just use [HideInInspector] to prevent

    someone playing with a public member variable?

    Reply

    Jonathan MacAlpine 11 months ago

    I've been trying to sort out the rewriting-custom-inspector jazz, but I can't make heads

    of tails of it. When I try to enter the code as-is, much of it won't compile (for example,

    due to the SplitCamelCase method present). Do the three methods listed here belong

    under one common class (BaseEditor)?

    I'm fairly new to Unity and to C# in general, and I can't sort it out! :(

    Reply

    Jonathan MacAlpine 11 months ago

    What are your thoughts on how Unity mingles assets and folders together in the Project

    view? Do you think it's worthwhile to set up the folder hierarchy in such a way that there

    are only ever folders *or* assets within a folder?

    Reply

    Herman Tulleken 11 months ago Jonathan MacAlpine

    Yes, it is annoying. I do think it is a good idea to set it up as you describe.

    Looking at our projects, I see we have not done it religiously, but is almost a

    natural consequence of just keeping things neat.

    Adam Reed a year ago

    Thanks for the tips especially the ones on the custom editor. I have one concern

    though: I noticed that you did not use SerializedObject for your editor, is there a reason?

    I have been planning on building a Editor base class that used reflection and the

    SerializedPropertys to allow the flexibility I want and also the benefits from using

    SerializedObject (prefab override, undo, multi editing etc) but I wonder if there is

    somethingthat I am not aware of that made you decide not to in your example.

    Thanks again for the wonderful tips.

    Share

    Share

    Share

    Share

    Share

  • 19/08/13 50 Tips for Working with Unity (Best Practices) | devmag.org.za

    devmag.org.za/2012/07/12/50-tips-for-working-with-unity-best-practices/ 31/31

    Load more comments

    Reply

    Thanks again for the wonderful tips.

    Reply

    Herman Tulleken a year ago Adam Reed

    There is a reason, although not a very good one. I could not get it to work, or it

    did not work as expected (or I wanted it to work). I started using it, but gave up at

    some point. It would be nice if you can get it to work to post an example

    somewhere.

    Reply

    Henning a year ago

    Thank you SO much! As I'm new to Unity (12 days) and just putting the final tuchses on

    my first Unity game. It's really nice to find some good solid guidelines/best practices.

    Now I have a better grasp of what to do different for my next game, to make the

    process a lot easier.

    What is you input on GUI design.. After testing my game in different resolutions and

    aspect ratios, I'm getting a serious urge to make all menus using Text Meshs instead of

    using UnityGUI/Skin placement hell.

    Thanks again.

    Reply

    Herman Tulleken a year ago Henning

    A GUI is one of the few things that is almost in every game; I can't understand

    why better systems has not been available for much longer. (At least the GUI

    system in Unity 4 looks great).

    We always use EZGUI, because Unity's build-in GUI framework is so slow (on

    mobile it makes a huge difference). It has it's own sets of problems, but I think

    overall it's a powerful system.

    Com m ent feed Subs cribe via em ai l

    Share

    Share

    Share

    Share