Map camera system¶
The camera system is greatly influenced by MapControl and it can be configured with the following configuration fields:
Name | Type | Description | Default |
---|---|---|---|
camoffset | Vector3 | The initial instance.camoffset of the camera while on this map and the value set when ResetCamera is called while on this map |
MainManager.defaultcamoffset if the magnitude is 0.2 or lower which is normally (0.0, 2.25, -8.25) |
camangle | Vector3 | The initial instance.camangleoffset of the camera while on this map and the value set when ResetCamera is called while on this map |
MainManager.defaultcamangle if the magnitude is 0.2 or lower which is normally (10.0, 0.0, 0.0) |
camlimitneg | Vector3 | The lower limit of the camera's position for this map expressed in each axises | (-999.0, 0.0, -999.0) |
camlimitpos | Vector3 | The upper limit of the camera's position for this map expressed in each axises | (999.0, 999.0, 999.0) |
rotatecam | bool | If true, it changes the camera movement to look at the actualcenter when RefreshCamera is called which overrides the normal movement logic |
false |
centralpoint | Vector3 | The initial value of actualcenter which is the center point of the radius limit. If tieYtoplayer is false or camtarget is null, this is effectively equivalent to actualcenter . Otherwise, the x and z components of actualcenter are equivalent to this field, but the y component gets overriden to the camtarget y position. Additionally, this field is the center of a Wind if its owncenter is false on its Start |
Vector3.zero |
tieYtoplayer | bool | When true, it causes the y component of actualcenter to be overriden in FixedUpdate to the camtarget y position if it's not null which effectively lets the camera follow its target in the y axis. If this field and rotatecam are true on RefreshCamera, the camera x angle is always set to 0.0 which fixes the x rotation in place |
false |
tetherdistance | float | If above 0, this becomes the max radius from actualcenter the camera can be positioned at during RefreshCamera via the radius limit |
-1.0, but it is overriden if tetherYLerp x component is above 0.0 |
tetherYLerp | Vector3 | Only applies if tieYtoplayer is true and camtarget isn't null. This field contains the 3 parameters to a lerp operation to do on FixedUpdate to update tetherdistance if the x component is above 0. The lerp will be done from the x component to the y component with a factor of camtarget y position / the z component. NOTE: This feature is complicated, see the section below for details |
Vector3.zero |
roundways | Transform[] | Only the first element matters. If the first element exists, rotatecam is true and we aren't in an inside, the corresponding Transform will be positioned relative to the camera's forward vector on FixedUpdate in x and z (the y component is always 5.0). The position is multiplied by lightoffset before being set. NOTE: This is very specific to the AntTunnels map |
Empty array |
lightoffset | float | If roundways[0] exists, rotatecam is true and we aren't in an inside, this field will be a multiplier applied to the position to set roundways[0] in FixedUpdate. NOTE: This is very specific to the AntTunnels map |
5.0 |
Most of the camera system is actually managed by MainManager via some fields that act as a state machine. More information can be found on the general camera system documentation.
However, the current map is what has the biggest influence on the camera initially so the parts that are specific to MapControl will be documented here.
Main Camera system influence¶
There are several parts MapControl influences of the main camera system.
Initial position and angles¶
The initial values of instance.camoffset
and instance.camangleoffset
are dictated by the MapControl's camoffset
and camangle
fields. This gives a starting default position, but they will default to their respective values if the prefab didn't had values set for them. It should be noted that these are only initial values: the game can override them and in the case of a DoorOtherMap, it's possible they get overriden very early during map loading
Camera limits¶
MapControl also allows to restrict the camera's positioning during RefreshCamera. The only requirement to make use of this feature is the current MapControl isn't null (which is only the case when loading a map).
There are 2 types of limits that can be enforced. They stack and are applied in the order mentioned (this doesn't include the local position displacement which is done after both of these):
- Hard positional limit: This limits the camera to have a position that always falls between
camlimitneg
andcamlimitpos
. It's a very hard limit: the camera will never be allowed to go beyond this range. It should be noted that these fields only initial values: the game can override them and in the case of a DoorOtherMap, it's possible they get overriden very early during map loading - Radius limit: This limits only applies if
tetherdistance
is above 0.0 (it has a value set) and we aren't in an inside. This limits the camera position to fall inside a circle where the center isactualcenter
and the radius istetherdistance
More details on the radius limit¶
About actualcenter
, while the initial value of actualcenter
is centralpoint
which is a configuration field, its y component can get overriden by FixedUpdate to instance.camtarget
y position if tieYtoplayer
is true and camtarget
isn't null.
Basically, by setting tieYtoplayer
to true, it also configures the radius limit to ignore the y component if the camera is set to move towards instance.camtarget
since they'll be the same in this limit check so only the x and z component matters.
As for tetherdistance
, while a constant value can be set in the prefab, it can get overriden by FixedUpdate and leave its management to tetherYlerp
if its x component is above 0.0. How it works is on each FixedUpdate where tieYtoplayer
is true and instance.camtarget
isn't null, tetherdistance
is set to a lerp from tetherYLerp
.x to tetherYLerp
.y with a factor of instance.camtarget
y position / tetherYLerp
.z.
tetherYLerp
however is a relatively complicated features that warrants more explanation of what it tries to do.
More details on tetherYLerp
¶
This configuration field essentially is an attempt to address a simple problem that technically was already solved. In a rotatecam
map with tieYtoplayer
enabled, the camera will want to LookAt the actualcenter
of the map, but it will do so once its position and offsetting were updated. This means all of this happens AFTER the camlimitneg
, camlimitpos
and tetherdistance
constraints were processed.
The problem comes with a map that fits those conditions, but is also layed out vertically. This is the case particularily with the WizardTowerStairs
map which fits all of the above to run into this problem.
The problem involves the tetherdistance
constraints as the camtarget
(usually the player
)'s y position. As it increases, it means the camtarget
is going further and further away from the map
's actualcenter
so it means that the distance eventually gets larger than tetherdistance
which will block the camera from going upward as the player goes up. The result is the camera will be forced the look downward because it still has to follow its camtarget
, but is forced to look down towards the map's actualcenter
instead of having its y follow its target.
However, this problem would have already been solved: the game does actually updates actualcenter
's y to match the camtarget
's y in FixedUpdate when tieYtoplayer
is enabled which it is in this case. The reason this fix doesn't work is because for some reason, the camlimitneg
's y and camlimitpos
's y of this map are set to 0.0. This forces the camera's y to be 0.0 and unfortunately, this limit applies BEFORE the tetherdistance
one. Please note that this is separate from camoffset
which is free to be applied after all limits so camoffset
ignores those limits.
Since the camera is forbidden to go up, but the actualcenter
's y follow the player, this creates the exact same y difference that will incorrectly impact the tetherdistance
check. Effectively, due to the map's misconfiguration, it has unfixed the problem's fix.
Instead of correctly configuring the map, what was done was apply a workaround which is what tetherYLerp
is. What this feature does is to allow tetherdistance
to progressively change from a value to another as the camtarget
's y changes. All of this is done with a lerp between the 2 desired values (x and y components) where the factor is the camtarget
's y / a third configurable number (the z component).
This essentially allows to compensate this issue by increasing tetherdistance
as the camtarget
's y increases. It is an improper way to perform this workaround because it now allows the camera to go beyond the desired bounds in x and z, but in practice, this doesn't happen because the tetherYLerp
configured for this map happens to tuned well enough to not let the camera go too far as well as keeping the default camoffset
.
Other than WizardTowerStairs
, the only other map that technically uses this feature is MysteryIsland
, but this one has it missconfigured because the y and z components are left at 0.0. This leads to unexpected behaviors such as the lerp factor being a division by 0.0, but in practice, this feature doesn't do anything because the tetherYLerp.x
is too high to be impactful and even if it was disabled entirely, it wouldn't have restricted the camera in a meaningful way.
In the end, it is not recommended to use this feature and to instead configure the map properly. The actualcenter
's y value already correctly follows the camtarget
's y so it is not necessary to apply such a questionable workaround.
roundways[0]
¶
This configuration field is not really a feature, but more a specific implementation of a moving light present in the AntTunnels
map.
It only cares about the first element of the array and it only positions it in a way that make sense specifically on this map. This implies it's not a feature meant to be used on any other map. In that map, roundways[0]
is a point light that needs to move such that it is aligned with the MainCamera
's forward vector such that it is positioned towards it from the origin in x/z (the y is hardcoded to be 5.0). This also involved another specific field to this map: lightoffset
which scales the whole vector.
The math is incorrect and wrong, but it does overall achieve the effect of moving alongside the camera in a relatively aligned fashion. It allows the map to have this moving light effect.
However, it is not meant to be used on any other map and it also assumes the map it is used is a rotatecam
one which AntTunnel
happens to be. Using this feature on any other map can have unintended consequences.