- Home /
World Space UI facing multiple Cameras (Billboard)
I'm working on a split screen multiplayer game. I have many world space UI canvas always facing the camera (billboard). I have a hard time making them face both cameras at the same time.
I tried to rotate the canvas to face the cameras using Camera.onPreCull and Camera.onPreRender callbacks. The object do receive the callback from both cameras every frame, but only the rotation from the last camera to be rendered seems to affect the UI object. If I replace the object for a standard 3D plane with a MeshRenderer, everything works as expected, ie the plane faces both cameras. I also tried OnWillRenderObject but it doesn't work as it needs to be attached to a gameObject with a Renderer, which is not the case for a Canvas.
Here is my camera facing script:
public class LookAtCamera : MonoBehaviour
{
void OnEnable() { Camera.onPreRender += PreRender; }
void OnDisable() { Camera.onPreRender -= PreRender; }
void PreRender(Camera cam)
{
transform.LookAt(transform.position + cam.transform.rotation * Vector3.forward,
cam.transform.rotation * Vector3.up);
}
}
I ran out of solutions and I implemented a workaround by duplicating Canvas for each cameras using camera specific layers on each of them:
public class DuplicateGameObjectOnMultipleLayers : MonoBehaviour
{
[SerializeField]
LayerMask layers;
bool first = true;
void Start()
{
for(int i = 0; i < 32; i++)
{
if(((1 << i) & layers) != 0)
{
if(first)
{
gameObject.layer = i;
first = false;
}
else
{
var newGameObject = (GameObject)Instantiate(gameObject, transform.position, transform.rotation, transform.parent);
newGameObject.gameObject.layer = i;
newGameObject.GetComponent<DuplicateUIOnMultipleLayers>().enabled = false; //Avoid infinite recursion
}
}
}
}
}
I had to modify the LookAtCamera scripts to apply rotation only for cameras that renders the object's layer:
public class LookAtCamera : MonoBehaviour
{
void OnEnable() { Camera.onPreRender += PreRender; }
void OnDisable() { Camera.onPreRender -= PreRender; }
void PreRender(Camera cam)
{
if((cam.cullingMask & (1 << gameObject.layer)) != 0)
{
transform.LookAt(transform.position + cam.transform.rotation * Vector3.forward,
cam.transform.rotation * Vector3.up);
}
}
}
Clearly not the best solution.
Does anyone know how to have a world space UI canvas facing multiple camera at the same time without duplicating it?
@lsdrambo Hey! Did you find more elegant solution? :) Also ran into the same issue. Thanks.
No, I'm still using the "duplicating canvas solution" ...
I have this problem as well. I'll try the double canvas solution...
Your answer
Follow this Question
Related Questions
Restricting Canvas navigation for each player 0 Answers
Mobile Multiplayer touch controls 0 Answers
Splitscreen w/ different GUIs on each camera 2 Answers
How to make a split-screen? (2 cameras rendering at same time) 4 Answers
all ui buttons applying to player 1, how do i make them apply to the player that clicked 2 Answers