I have this code for making each leaf on my tree look at the camera:
using UnityEngine;
public class Billboard : MonoBehaviour
{
private Transform m_transform;
private Transform m_camTransform;
private void Awake()
{
m_transform = transform;
m_camTransform = Camera.main.transform;
}
private void Update()
{
if (m_camTransform != null)
{
m_transform.LookAt(m_camTransform);
}
}
}
There is a difference of 70 FPS when this Update method is commented out. This script is on each leaf on my trees. Given the number of trees I have in scene, there are roughly 600 leaves in the scene with the script.
I have tried offloading this to a BillboardManager class:
using UnityEngine;
public class BillboardManager : MonoBehaviour
{
private Transform m_mainCamTransform;
private void Awake()
{
m_mainCamTransform = Camera.main.transform;
}
private void Update()
{
foreach(Billboard billboard in Billboard.m_billboards)
{
billboard.m_transform.LookAt(m_mainCamTransform);
}
}
}
But I only see 10 FPS difference in the 70 FPS loss…
Right well the problem with LookAt is twofold:
- it’s not making your billboards right because they are looking at the camera’s location and not it’s focal plane
- each leaf needs a separate calculation
Instead you should try:
void Update()
{
var billboardForward = -m_mainCamTransform.forward;
foreach(var billboard in Billboard.m_billboards)
billboard.m_transform.forward = billboardForward;
}
Or instead you could actually rotate the first billboard using -m_mainCamTransform.forward and then set the rotations on the others (it might be faster).
There’s an article on Unity Gems that I wrote concerning the effects of LookAt versus setting transform.forward on billboards.
You can skip some of the processing by doing different type of calculation in these 3 scenario:
- When the tree is in view, and the camera is quite close to it
- When the tree is in view, but the camera is at a certain distance from it
- When the tree is not in view.
Close up Tree
-
LookAt()
for all leaves on the tree
Faraway Tree
- In
Start()
, define the approximate center of the leaves. Assign the center to a empty object
-
emptyObject.LookAt(camera)
.
- Copy the rotation of the
emptyObject
to all the leaves
Not in view Tree
- Do almost nothing
- You need to check whether part of the tree is in view of the camera
You will be switching between these 3 stage. By checking the distance between the camera and your tree, you can determine whether you should use CloseUp and Faraway.
If the tree is far enough, rotation returned by LookAt()
of a group of leaves of the same tree will differ by a small margin. You will skip a good portion of calculation here by approximate and use the average rotation.
If the tree is not in view at all, why even bother to make the billboard LookAt()
the camera? However, you need to be careful on deciding whether a tree is in view or not ( there are times where partial of the tree in view, and close up to the camera )