Camera
Two components: CameraComponent is the camera itself, CameraFollowComponent is the behaviour that makes it track something.
CameraComponent
Priority
Which camera wins when a scene has more than one. Higher takes over. Read and write — switching cameras is a priority change, not an enable/disable dance.
GetComponent<CameraComponent>().Priority = 10;OrthographicSize
Half the camera's visible height in world units. Smaller is more zoomed in. Read and write.
private System.Collections.IEnumerator ZoomTo(float target, float duration)
{
CameraComponent cam = GetComponent<CameraComponent>()!;
float start = cam.OrthographicSize, t = 0;
while (t < duration)
{
t += Time.UnscaledDeltaTime;
cam.OrthographicSize = start + (target - start) * (t / duration);
yield return null;
}
}WorldToScreen(Vector3 world)
Projects a world position into screen space: pixels, origin top-left, +Y pointing down — the same convention as Input.GetMousePosition(), so a value from one can be handed straight to the other.
Vector2 screen = cam.WorldToScreen(enemy.Translation);
m_HealthBar.Translation = new Vector3(screen.X, screen.Y, 0);ScreenToWorld(Vector2 screen)
The exact inverse: unprojects a screen position onto the world's Z=0 plane, where every sprite, collider and particle lives unless deliberately placed off it.
Vector3 world = cam.ScreenToWorld(Input.GetMousePosition());
Particles.Spawn("Effects/Click.jparticle", world);World is +Y up, screen is +Y down
This pair is the boundary between the two conventions, and the only place a Y sign legitimately flips. Round-tripping a value through both returns what you started with. Both read (0,0) if the camera's viewport size hasn't been set yet — that is, if you call them before the scene's first frame.
CameraFollowComponent
Smooth follow, screen shake, and camera bounds.
You don't have to add this component first
Every setter here adds the component automatically on first write, and every getter returns a sensible default if it isn't there yet. So a script that only ever writes follow settings just works, even though HasComponent<CameraFollowComponent>() would have read false a moment earlier.
FollowTarget
The entity to follow, or null for none. Read and write.
GetComponent<CameraFollowComponent>()!.FollowTarget = FindEntityByName("Player");Offset
Where the camera sits relative to its target, as a Vector3. Defaults to about (0, 0, 10). Read and write.
follow.Offset = new Vector3(0, 2, 10); // look slightly ahead/aboveDamping
How sluggishly the camera catches up, per axis. Defaults to about (0.15, 0.30, 0) — a little looser vertically than horizontally, which is what stops a platformer camera jittering on every small hop. Larger is slower and smoother. Read and write.
follow.Damping = new Vector3(0.10f, 0.40f, 0);AddShake(float trauma)
Adds screen shake, 0 to 1. It decays automatically every frame, so you call it once per event rather than managing a timer.
protected override void OnCollisionEnter(Collision2D collision)
{
m_Camera?.AddShake(0.4f);
}Calls compound rather than overwrite — three explosions in quick succession shake harder than one, with the total clamped to 1. That's usually what you want; if it isn't, gate the calls yourself.
SetBounds(Vector2 min, Vector2 max)
Confines the camera to a rectangle in world space, so it stops at the edges of a level instead of showing the void beyond it.
follow.SetBounds(new Vector2(0, 0), new Vector2(200, 40));ClearBounds()
Removes the confinement — for a boss arena that opens out, or a cutscene that needs to pan away.
Example: a platformer camera
using JoystickEngine;
public class LevelCamera : GameEntity
{
private CameraFollowComponent? m_Follow;
protected override void OnCreate()
{
m_Follow = GetComponent<CameraFollowComponent>();
m_Follow!.FollowTarget = FindEntityByName("Player");
m_Follow.Offset = new Vector3(0, 1.5f, 10);
m_Follow.Damping = new Vector3(0.12f, 0.35f, 0);
m_Follow.SetBounds(new Vector2(0, 0), new Vector2(240, 60));
}
public void OnExplosion(float strength)
{
m_Follow?.AddShake(strength);
}
}See also
- GameEntity —
FindEntityByName,Translation - Input — mouse position, in the same screen space as
WorldToScreen - Coroutines — for camera moves over time