First of all, you need to understand what exactly you want for this camera system.
1) As developer I want to define rooms, where camera movement will be limited by room edges.
Here you can see that camera really blocked on bottom and left side of first room, and not shows things behind it.
So, we may say that edges of this room is “closed” for camera movement.
2) As developer I want to define how camera moves between rooms.
Transition can be smooth - when camera position interpolates between rooms.
notice that bottom edge of this room is closed.
And transition can be cut - when camera “teleported” between rooms (this situaton is for closed edges also).
In situation when for 2 rooms edges are “opened”, between them camera simply moves with character, without any additional behavior.
3) As developer I want to change camera offset (zoom) in every room.
Yep, I really want it. Because in big rooms camera should be far from character, and in small rooms camera should be near.
AND (!) if room small, and all it’s edges are closed, I should calculate camera offset for this room, so camera view (frustrum) is fit to room correctly.
Here is one additinal situation:
Notice that when character near the door, camera offset is near, but when he moved forward, camera offset becomes bigger.
This is when we have “room in room”. So, it’s just smaller room (with smaller camera offset) placed in bigger room (with bigger camera offset), and this smaller room have higher priority for camera calculations!
How this should work?
I use special “Camera Volumes”, which specifies my game rooms and additional parameters for camera. It’s actor with box and camera (for preview offset) components, edge indicators and additional things.
I detect when character overlaps new camera volume, add this volume to array of volumes overlapped by character, sort this array to get volume with higher priority and finally pass parameters of this volume to camera manager.
So my system works by events. Ofcourse you can calculate it every tick, using “GetOverlappingActors”, filter it by camera volume class and so on. But you should ask yourself is it really necessary. Because overlapping new camera volume is rare situation even in terms of 1 second, not tick.
How to limit camera movement?
My camera have -X orientation in world, and moves in YZ plane.
I know max and min coordinates of volume. You can see it on screen above:
- max - left top nearest point
- min - right bottom far point
So it’s already limits of room. If some edges (where camera can pass) should be opened, I define opened/closed edges of volume by editable boolean variables in level, and add/subtract 10000 uu to min/max limits.
- top edge opened - max Z = max Z + 10000
- right edge opened - min Y = min Y - 10000
To calculate correct offset for camera in this specific volume I use desired one set in volume parameters, but I need to understand is my screen fits to this volume with this offset or not. Maybe its bigger than I need. And if yes, my offset should be recalculated.
I have compare ratio of this volume and camera aspect ratio:
- if volume ratio >= camera ratio, so this volume is “horizontal”, in comparison with my screen.
- if volume ratio < camera ratio, so this volume is “vertical”, in comparison with my screen.
So, if my desired offset = 2000, but it’s not fit screen into volume, it will be recalculated to, for example, 1752.128524, and:
- in “horizontal” volume camera fits by volume Z, and can move only by Y.
- in “vertical” volume camera fits by volume Y, and can move only by Z.
Then, to do things correctly, I calculate real screen coordinates in YZ plane:
With it, I can understand than my max and min screen coordinates is in the volume.
And now I can calculate camera position, and clamp it to this max and min of volume.
Also, when your character overlaps volume, you can detect where it happen by hit result.
So, you know exactly which edge you pass, and by booleans like “edge open”, “edge cut” you can create smooth or cut transitions.
How it may be done easier?
For example, if you have really 2d game, with the same camera offset in all rooms, and camera transition between this rooms is always the same (for example smooth), so maybe you can use ray tracing and so on…