Tuesday, July 22, 2014

Unity 3D: Partial Classes with C#

Typically, Unity requires you to have one class per script, which can be a bit of a drag if you've got a larger, more complex class. Did you know that you can split that class up into multiple files using C# partial classes?

The method is simple. Let's say you create a C# script called "PlayerCharacter". You'll have a class generated for you automatically in the .cs file, with contents like so:

using UnityEngine;
using System.Collections;

public class PlayerCharacter : MonoBehaviour{

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


We'd like to add a pretty complex bit of code just pertaining to armor. We'd like to keep it in this class, but we'd like to separate it from the rest of the code in this file. Well, first, add the "partial" keyword before "class" in your declaration:

public partial class PlayerCharacter : MonoBehaviour

Now, go ahead and create another C# script, and call it "PlayerCharacter.Armor". Open it up in MonoDevelop and you'll see something like this:

using UnityEngine;
using System.Collections;

public class PlayerCharacter.Armor : MonoBehaviour {

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


We're going to get a parsing error, because we can't have a "." in our class name. Use the "partial" keyword again, and remove the ".Armor" portion of the class declaration, so we're using the exact same declaration we used in the other .cs file:

public partial class PlayerCharacter : MonoBehaviour

Here we have two files that represent different parts of the same class. Keep in mind one important thing: if you're inheriting from MonoBehaviour as we did above, you need to make sure that you don't have your built-in methods (such as "Start ()" and "Update ()") in multiple files. This is a single class spread out over multiple files, so you can't declare something multiple times. In the example above, we would simply remove "Start ()" and "Update ()" from one of the files and be good to go.

You can make as many files as you want, naming them with the convention "className.x". Anything that is declared in any of the files is available when working with any of the other files. For example, if I declare a private bool called "isWearingArmor" in the "PlayerCharacter.Armor" file, I can still access that bool from the "PlayerCharacter" file. It's all one big class, and is treated as such by the IDE and the compiler.

Of course, be wary: if you're making a class that is only convenient to use if you spread it out over a dozen files, you may be trying to jam too much into one class. We're completely disregarding class design considerations (and the associated holy wars) to show this technique. Ultimately, it's up to you to design your classes how you see fit.

4 comments: