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.

Let’s take the following simplified example:

public class ExampleBehaviour : MonoBehaviour
{
    // A list of game objects that are somehow linked to this example behavior
    public GameObject[] linked;
}

Now let’s assume that for some reason that we would prefer to change to the following variation, for example to simplify component lookups:

public class ExampleBehaviour : MonoBehaviour
{
    // A list of MyOtherBehaviour components that are somehow linked
    public MyOtherBehaviour[] linked;
}

Updating the data structure may seem like a relatively straightforward task. An effective solution would be to display an appropriate confirmation message before installing the latest update via the asset store, followed by updating existing prefabs and scenes. Unfortunately the Unity API does not appear to offer an easy way of making these changes.

So the challenge here is to alter the data structure without causing too much distress for existing projects. Here are two options:

Option 1 - Add an additional property

The new data structure could be implemented easily by introducing a new property, and flag the one that is no longer required as Obsolete. Existing instances of the component would need to be updated (possibly using an editor script) for best performance at runtime.

public class ExampleBehaviour : MonoBehaviour
{
    // A list of MyOtherBehaviour components that are somehow linked
    public MyOtherBehaviour[] linkedComponents;
 
    // Do not use this property anymore!
    [HideInInspector, System.Obsolete("Please update existing instances of component...")]
    internal GameObject[] linked;
}

Instances of the component that are not updated at edit-time can automatically update themselves at runtime with the additional performance overhead. A warning or error message can also be logged to the console window suggesting that the developer uses the custom editor update script.

This approach will lead to a redundant property which may inadvertently still contain unwanted data. Developers who are using the runtime API may also become confused over this change.

Option 2 – Replace behavior class with a new version

A new version of the MonoBehaviour could be defined to represent the desired data structure. The extension can easily be updated to add the new version of the component while existing instances will initially continue to use the original version.

[System.Obsolete("Please update existing instances of component...")]
public class ExampleBehaviour : MonoBehaviour
{
    private static bool s_LOGGED = false;
 
    public GameObject[] linked;
 
    private void OnEnable()
    {
        if (!s_LOGGED) {
            Debug.LogError("Please update existing instances of component...");
            s_LOGGED = true;
        }
    }
 
}
 
public class ExampleBehaviourV2 : MonoBehaviour
{
    public MyOtherBehaviour[] linked;
}

Again an editor script would be needed to automate the update process as much as possible. The benefit of this approach is that once existing objects have been updated, there is no additional overhead “wasted” on dealing with deprecated functionality at runtime.

The disadvantage is that we would be stuck with the older version of the class for a while (along with an update script).

Conclusion

For Rotorz Tile System option 2 seems to be the most appropriate. Please leave comments, I would love to hear the views of others! How would you guys update your extension whilst at the same time imposing minimal impact upon existing projects?