I have a problem with a script and timeline.
I have several hundred objects in my scene used to label items. When the camera moves through the scene the objects point towards it for visibility, using the following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class alwaysFaceCamera : MonoBehaviour
{
private Transform camera;
void Start()
{
camera = Camera.main.transform;
}
void Update()
{
transform.LookAt(camera);
}
}
Which seems very straightforward. However, now I would like to make the sequence more useful (meaning able to see more parts of the scene) by using several cameras in sequence.
To do this I have simply set up a list of cameras as animation tracks in Unity timeline. Each are deactivated in the inspector until activated by the timeline, each has the tag MainCamera (because they are deactivated until the activation track activates them).
The sequence of cameras works fine and is very flexible, but the problem is the LookAt script no longer works. It finds the first camera and then stops. I think this may be because the main camera is being set in void Start(); and is not being updated. I’m now not clear about how a script such as the above should interact with the timeline (TBH I thought activating and deactivating the cameras in the timeline would simply work because there would only be one active main camera in the scene at a time).
Any help appreciated, I should probably mention 97% of my time is spent doing art and about 3% coding. Thanks.
Solution B, Scripts:
LookAtCamera.cs
using System.Collections.Generic;
using UnityEngine;
[ExecuteAlways]
public class LookAtCamera : MonoBehaviour
{
public static List<LookAtCamera> instances = new List<LookAtCamera>();
void OnEnable () => instances.Add( this );
void OnDisable () => instances.Remove( this );
}
LookAtCameraSystem.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
[ExecuteAlways]
public class LookAtCameraSystem : MonoBehaviour
{
[SerializeField] Method _method = Method.LookAt;
static LookAtCameraSystem _instance = null;
void Awake ()
{
if( _instance==null )
_instance = this;
else
Debug.LogError($"There is more that one instance of {nameof(LookAtCameraSystem)}, this will result in reduced performance and undefined behaviour.",gameObject);
}
void OnEnable () => RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering;
void OnDisable () => RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering;
void OnBeginCameraRendering ( ScriptableRenderContext context , Camera camera )
{
if( _method==Method.LookAt )
ForeachLookAt( LookAtCamera.instances , camera );
else if( _method==Method.Align )
ForeachAlign( LookAtCamera.instances , camera );
}
void ForeachLookAt ( IList<LookAtCamera> list , Camera camera )
{
for( int i=0 ; i<list.Count ; i++ )
list*.transform.LookAt( worldPosition:camera.transform.position , worldUp:camera.transform.up );*
- }*
- void ForeachAlign ( IList list , Camera camera )*
- {*
-
var rotation = Quaternion.LookRotation( forward:-camera.transform.forward , upwards:-camera.transform.up );*
-
for( int i=0 ; i<list.Count ; i++ )*
_ list*.transform.rotation = rotation;_
_ }_
_ public enum Method { LookAt = 0 , Align = 1 }_
_}_
_> LookAtCamera is intended to work as kind of a tag where LookAtCameraSystem is a system that processes all of the tag instances and should be considered a singleton, so create a single instance of this component in your scene and no more._
_> Note: Remove [ExecuteAlways] attribute or disable local LookAtCameraSystem instance if you don’t want it to execute in scene view while working._
_### Solution A, Shaders:*
Replacing this script with a “mesh look at camera” shader will resolve this issue auto-magically.
_
![mesh look at camera shader graph][1]
[Imgur: The magic of the Internet][2]
_
Note:
This shader works fine while object rotation is zero-ed and scale is uniform. Removing this requirement is technically possible but introduces silly and totally unnecessary calculations (in shader graph case). So, just make sure rotation is ( 0 , 0 , 0 ), scale is (1,1,1) (or (1.5,1.5,1.5)) and carry on.
_
_[1]: Imgur: The magic of the Internet
_[2]: Imgur: The magic of the Internet
@andrew-lukasik Many thanks for this! Must admit I would not have even thought about a shader as a possible solution, so this opens up a lot of new possibilities to explore too. Setting rotations to zero should not be an issue.
Just one thing… Don’t suppose you have a higher res version of the screengrab? The web page isn’t allowing me to enlarge it much, it’s a bit hard to read! 
(@moderators, a feature similar to the way of displaying code but for graphs might be worth thinking about for the future? Cheers).
First, thanks again for the help - really appreciated. In fact you did mention the scale issue, but I’d dived straight into the graph and missed it. Creating a correctly sized object in a DCC app won’t be a problem.
But TextMesh… Drat. I was going to point out the TextMesh element is only parented to the mesh with the shader and wondered if this would make a difference - I’ll run a quick test to see but I can imagine why that would be an issue. I’ll have to keep looking I suspect.