Code organizations: How to organize game code and classes

organize game code

I always had problems to organize game code in a nice and readable structure. With that, I decided to write down the guidelines that I use when developing my games.

These rules are not gold but are just  simple guidelines that I use on a daily basis to write my code.

If you believe another method is better, in that case, go ahead with your system. The important thing here is to have some sort of guidelines to organize game code and give it a nice structure.

 

Order of items in a class:

I use the following order when I have to write something inside one of my class.

Within a class, struct or interface:

  • Constant Fields
  • Fields
  • Constructors
  • Finalizers (Destructors)
  • Delegates
  • Events
  • Enums
  • Interfaces
  • Properties
  • Indexers
  • Methods
  • Structs
  • Classes

Within each of these groups order by access:

  • internal
  • protected internal
  • protected
  • private

Within each of the access groups, order by static, then non-static:

  • static
  • non-static

Within each of the static/non-static groups of fields, order by readonly, then non-readonly : 

  • readonly
  • non-readonly

An unrolled list is 130 lines long, so I won’t unroll it here. The methods part unrolled is:

  • public static methods
  • public methods
  • internal static methods
  • internal methods
  • protected internal static methods
  • protected internal methods
  • protected static methods
  • protected methods
  • private static methods
  • private methods

 

How to divide and organize game code:

You can use #region if you’re coding in C# or a similar keyword in other languages. The main goal of the region keyword is to divide your code into sections in order to find faster what you’re looking for inside one of  your classes and to better divide the class into sections.

Example:

public class myClass 
{
  #region FIELDS 
  Your fields here
  #endregion 

  #region PROPERTIES
  #endregion 

  #region MONOBHEAVIOR
  #endregion 
  ETC ETC
}

If you use region you’ll also have the ability to collapse entire regions of your code.

One class for all the constants:

I used to group all the constants that can be used over my code into one single class called Constants:

public static class Constants {

public struct SceneIds { public const float GRID_PADDING = 20; } public struct Tags { public const string TILE = “Tail”; } }

Doing so will have huge advantages such as, if you have to change something, that change will automatically be reflected everywhere in your code.

Take the Tag in the example before. If you want to change it, you don’t have to find all the places in your code where the tag is used, but just change the tag in the constant class and the tag will be updated everywhere it’s used.

Use properties over field variable

Examples from StackOverflow:

1.) Immutable property (passed into the constructor, or created at construction time). In this case, I use a field variable, with a read-only property. I choose this over a private setter since a private setter does not guarantee immutability:

public class Abc 
{ 
  private readonly int _foo; 
  public Abc(int fooToUse) { _foo = fooToUse; }
  public int Foo { get{ return _foo; } } 
}
  1. POCO variable. A simple variable that can get/set at any public/private scope. In this case, I would just use an automatic property.
public class Abc 
{
  public int Foo {get; set;} 
}

3. ViewModel binding properties. For classes that support INotifyPropertyChanged, I think you need a private, backing field variable.

public class Abc : INotifyPropertyChanged 
{ 
  private int _foo; 
  public int Foo {
  get { return _foo; } 
  set { foo = value; OnPropertyChanged("_foo"); }
} 

4. Private properties can be helpful in case you want to use the lazy instantiations:

private string _password; 
private string Password { 
   get {
       if (_password == null) 
            {_password = CallExpensiveOperation(); } 
       return _password; 
   }
}

Or if you want to be more elegant:

private Lazy _mytype = new Lazy(/* expensive factory function */);
private MyType MyType { get { return _mytype.Value; } }
// In C#6, you replace the last line with: private MyType MyType => _myType.Value;

Working with field and properties in your game engine (Unity example).

Most game engines give you the possibility to expose your public variables to the game editor in order to have the possibility to quickly change their values at run time.
In Unity it’s something like this:

public class MainPlayer : MonoBehaviour {
    public string myName;
    // Use this for initialization
    void Start () {
        Debug.Log("I am alive and my name is " + myName);
    }
}

This code creates an editable field in the Inspector labeled “My Name”.

EditingVarInspector

The problem here is that public strings are accessible by every class in your code because it’s marked as public. Unless this is what you want, I tend to not use public fields if not strictly necessary, and even if I have to, I prefer to use getters and setters to expose their values.

To solve this problem, most engines give you the possibility to create private fields and expose them to the editor. Example in Unity c#:

Public class Test : Monobehavior
{
  #region FIELDS
    [SerializeField]
    private GameObject _canvas;
    [SerializeField]
    private GameObject _gridContainer ;    
    #endregion

   #region PROPERTIES
     public GameObject Canvas { get {return _canvas;} }
    #endregion
}

In Unity, for example, we can expose a private field to the editor with the [SerializeField] keyword, and thanks to it we no longer have to use public fields.

 

Example class:

Here you can find a small class with a recap of all the things that I wrote before, or if you prefer, here the GutHub repo.

public class SpriteSheet : MonoBehaviour {

    #region FIELDS
    //Exsposing private field to the Unity editor
    [SerializeField]
    private GameObject _canvas;
    //Used for the lazy instantiations
    private string _password;
    
    #endregion

    #region PROPERTIES
    //Simple Properties creation
    public int Foo { get; set; }
    //Exsposing private field used by the editor example
    public GameObject Canvas { get {return _canvas;} }
    //Lazy instantiation example
    private string Password
    {
        get
        {
            if (_password == null)
            { _password = this.GeneratePassword(); }
            return _.password;
        }
    }
    #endregion

    #region MONOBHEAVIOR
    // Use this for initialization
    void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
    #endregion

    #region PUBLIC METHODS
    //Insert here your pubblic methods
    #endregion

    #region PRIVATE METHODS
    private string GeneratePassword()
    {
        return Constants.Secrets.password;
    }
    #endregion
}

Conclusion:

These rules are very simple, but thanks to them, I can quickly organize game code and use the same rules all over my project. Furthermore, using order in scripts allows you to be more efficient and have more readability in code.

If you have some suggestions or some best practices that you want to suggest to other readers please write them in the comments or send me a private message and I will add your content to the article.

 

Update: naming convention:

Was brought to our attention that the internal standard of the .NET CoreFX team insist on using the underscore-notation without giving any insights as to why. However, if we look closely to rule #3 it becomes evident that there is a system of _, t_, s_ prefixes that suggests why _ was chosen in the first place.

  1. We use _camelCase for internal and private fields and use readonly where possible. Prefix instance fields with _, static fields with s_ and thread static fields with t_. When used on static fields, readonly should come after static (i.e. static readonly not readonly static).
  2. We avoid this. unless absolutely necessary.

Written By
More from Marco

Code organizations: How to organize game code and classes

I always had problems to organize game code in a nice and...
Read More

2 Comments

    • Thanks for the link, It’ll probably take a week to understand all the rules in the documents that you send. I just needed a simple and quick way to organize my code. Btw when I’ll have time I’ll take a look at that documents to see if I can find something to improve the way I organize my code.

Leave a Reply

Your email address will not be published. Required fields are marked *