Edit: I screwed up the thread title! Oops. It should read ‘can we change it?’
This might not be the best example of why it is so clunky, but hear me out!
Let’s say I want an object in my scene to always face the camera - like a Billboard. I can create a script that will align an object to the camera. I would attach this script to the camera, and set the target object reference to the object I want aligned to the camera. So something like
public Transform TargetObject
void OnPreRender()
{
//align 'TargetObject' to this camera
}
This works fine for one camera. Not a great solution but it works. But now the camera has to be in charge of moving around and ‘dealing with’ other objects. Those objects should be handling themselves and aligning correctly without the help of the camera object. Not to mention that this system would be a pain to maintain with multiple cameras - each camera would need this script attached and the references would need to be updated on all of them every time you want to change the ‘target’ object.
I think these camera methods are a little clunky for this reason. Sure, some scripts should run on one specific camera only. But it isn’t always the case, so these ‘camera specific’ methods become pretty useless.
Can we instead have a static event on the Camera class that we can register to for each of these ‘camera specific’ methods? It would work something like this"
void Awake()
{
Camera.OnPreRender += OnPreRender;
}
void OnPreRender(Camera currentCamera)
{
//align my self to 'currentCamera', where 'currentCamera' is the camera being rendered
}
Unity would invoke the Camera.OnPreRender event once for every camera in the order that they are rendering. This means the MonoBehaviour can be attached to any object. In this example, the script above would be attached to the object that needs to be billboarded. The object will align itself correctly to all the cameras just before any of them render, because it will have its “OnPreRender(Camera)” methods invoked once for each camera.
This solution would be ‘backwards compatible’, in that it wont break scripts that make use of any of the ‘camera specific’ methods. Unity will still invoke MonoBehaviour.OnPreRender() etc. on every MonoBehaviour attached to a camera as usual.
These are all the ‘camera specific’ methods:
- OnPostRender
- OnPreCull
- OnPreRender
- OnRenderImage
- OnRenderObject
Thoughts?
Edit:
After some back and forward bellow, I think it would be nice to have (atleast) OnPreRender(Camera currentCamera) and OnPostRender(Camera currentCamera) methods ‘automatically’ invoked by Unity, regardless of where your script is attached.
If your script wants to react to a specific camera, use the current system. You would attach this script to the camera that you are interested in:
public class MyScript:MonoBehaviour
{
void OnPreRender()
{}
void OnPostRender()
{}
}
If you want your object to react to all cameras in the game, then you would do something like this and you would be able to attach this script on any game object (It doesn’t have to be attached to a camera - Unity will invoke these methods regardless, just like Update/LateUpdate/FixedUpdate)
public class MyScript:MonoBehaviour
{
void OnPreRender(Camera currentCamera)
{}
void OnPostRender(Camera currentCamera)
{}
}