Unity 5 and Unplanned Obsolescence

I have a Unity project in progress that interacts with some physics bugs present in the 4.6 series. So, incautiously, I decided to upgrade.

It's not that I was expecting damage. Ill-considered project mangling is one of the many perils I do not fear because of source control. But I know Unity 5 ships with an automatic source code transformer to update your use of some widespread removed API for component accessors, like Camera, Rigidbody, Renderer, etc.

What I encountered is a confluence of decisions that make life just a little bit worse for Unity developers. Unity has introduced a reason to use the "my" prefix in cross-component wiring.

I believe that zero-information prefixes, like "my" in module or class level code, are a code smell. They point to overlapping naming conventions.

C# already has one of these -- types and public members both use CapCamelCase by convention, a convention that Unity wisely ignores (but meanwhile ships with MonoDevelop, which fills your projects with capitalization warnings if you follow their lead). Now,

If your Unity 4 code looks like this:

if (target) {  
    Rigidbody2D targetBody = target.rigidbody2D;
    ...
}

...in Unity 5, this becomes:

if (target) {  
    Rigidbody2D targetBody = target.GetComponent<Rigidbody2D>();
    ...
}

Easy enough, and if Unity hadn't provided an automated transformation tool, I might have rolled my own.

However, there's another aspect of the way the API change was done that is going to frustrate me continuously: the component accessors (.camera, .rigidbody, .renderer, etc.) were marked deprecated and not removed. Is this what you expected? Look closer. They don't return their former types; instead, each returns a generic Component, which is sure to break most existing code. Again, with the automated code conversion, this doesn't seem like a big problem...but.

The previous example was a component manipulating a different GameObject's components. Let's consider the common case in which the component is manipulating its own components.

Vector3 velocity = camera.velocity;  
camera.orthographicSize = targetZoom;  

This code is a little bit sloppy, because as we know, the convenient accessors were just a facade to GetComponent<>. We knew this, and where it seemed worthwhile, we created a member variable and populated it with a single GetComponent call. We did this often, but maybe not always.

This becomes:

Vector3 velocity = GetComponent<Camera>().velocity;  
GetComponent<Camera>().orthographicSize = targetZoom;  

Ouch. The API change has made it painfully obvious where we've fallen short of best practice. So let's fix it:

Camera camera;  
...

void Awake() {  
    camera = GetComponent<Camera>();
}

void Update() {  
    ...
    camera.transform.position = new Vector3(next.x, next.y, current.z);
    camera.orthographicSize = targetZoom;
}

What's this?

CameraController.camera hides inherited member 'UnityEngine.Component.camera'. Use the new keyword if hiding was intended. (CS0108)

Okay. It's not a HUGE deal. I can just call it myCamera. But Unity people, this is stupid.

The API changed the signature of accessors, and also deprecated them. Changing the API reduces cross-module dependencies for your team. I get that. It also makes our code better, as I've shown above. But if my obsolete code is already broken, release those accessor names by simply removing them, because they're the obvious choice for caching variables.

Will it kill me to use Camera myCamera? Yes. I'll die a little on the inside, which is what I was doing writing my own engine.

Hey Unity people, kudos on the API cleanup. Obsoleting properties plus changing their signature and breaking them anyway is the worst of all worlds, and I think it was a mistake in an otherwise well-executed transition. I look forward to you removing these obsolete properties in an early Unity 5 point release. Thanks.