I'm trying to make a camera track two targets in a 2D game on unity but I can't quite get it to work.
This is the code I currently have, but it's changing the rotation in transform instead of position. the ortho size is changing but it is not properly tracking the center point between the characters. is there anyway I can fix this?
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour
{
private Camera cameraRef;
private GameObject[] playerPos;
void Start()
{
cameraRef = GetComponent<Camera>();
playerPos = GameObject.FindGameObjectsWithTag("Player");
Debug.Log(playerPos[0].transform.position);
Debug.Log(playerPos[1].transform.position);
Debug.Log(cameraRef.tag);
StartCoroutine(ZoomInOut());
}
// Update is called once per frame
void Update()
{
}
IEnumerator ZoomInOut()
{
while (true)
{
if (playerPos[0] != null && playerPos[1] != null)
{
Vector3 lookPoint = Vector3.Lerp(playerPos[0].transform.position, playerPos[1].transform.position, 0.5f);
cameraRef.transform.LookAt(lookPoint);
float distance = Vector3.Distance(playerPos[0].transform.position, playerPos[1].transform.position);
if (distance > (cameraRef.orthographicSize * 2))
{
cameraRef.orthographicSize = 0.05f;
// if (distance < (cameraRef.orthographicSize * 2))
//{
// cameraRef.orthographicSize -= 0.1f;
//}
}
else
if (distance < (cameraRef.orthographicSize))
{
cameraRef.orthographicSize -= 0.05f;
}
yield return new WaitForSeconds(0.02f);
}
}
}
}
CodePudding user response:
Well cameraRef.transform.LookAt does exactly what you described
Rotates the transform so the forward vector points at worldPosition.
Since your game is 2D anyway what you rather want to do is set the camera to exactly the same XY position
var lookPoint = (playerPos[0].transform.position, playerPos[1].transform.position) * 0.5f;
//Maintain the Z depth position
lookPoint.z = cameraRef.transform.position.z;
cameraRef.transform.position = lookPoint;
Also instead of
yield return new WaitForSeconds(0.02f);
rather use
yield return null;
The latter makes it run every frame. But anyway assuming 60FPS a frame takes about 0.017seconds so waiting0.02` will most probably mean you wait two frames since this value is not the exact time but rather the minimum time to wait/skip to the next frame.
And move this OUT of the if block!! If one of your objects is missing => endless loop -> Freeze/Crash of Unity and your app! You definitely want to wait one frame for every iteration of your while loop!
Actually you could as well do the thing in Update without the loop at all :)
And then instead of
cameraRef.orthographicSize -= 0.05f;
I would rather either use
// Take differences in the frame rate into account (jitter)
cameraRef.orthographicSize -= 3 * Time.deltaTime;
or directly interpolate
// Smooth interpolate -> if the target and current value are far apart
// this zooms faster and then becomes slower when already very close
// Adjust that "5" according to your needs
cameraRef.orthographicSize = Mathf.Lerp(cameraRef.orthographicSize, distance, 5 * Time.deltaTime);
Typed on the phone but I hope the idea gets clear
