Camera System
NWH Common provides camera switching, an extensible vehicle-camera base class, mouse/gamepad orbit
controls, and an interior-camera marker. The runtime types are in NWH.Common.Cameras.
Dependency context:
NWH.Common.Vehicles.Vehicleis abstract, and NWH Common does not ship a concrete vehicle component.CameraChangerandCameraInsideVehicletherefore require either a consuming NWH product with a concreteVehiclesubclass (such as Vehicle PhysicsVehicleController, AerodynamicsAircraftController, or DWPAdvancedShipController) or a project-definedVehiclesubclass. A Common-only project cannot add the abstractVehicletype as a component.
CameraChanger
CameraChanger enables one camera GameObject at a time and disables the others, including any
AudioListener on those same GameObjects.
Required hierarchy
CameraChanger must be on the Vehicle GameObject or one of its descendants. During Awake it
calls GetComponentInParent<Vehicle>(); without that parent it logs an error and does not register
for the vehicle lifecycle events.
Vehicle (Vehicle-derived component)
└── Cameras (CameraChanger)
├── Chase Camera
└── Interior Camera
With autoFindCameras enabled, the component collects every Camera on its own GameObject and on
any descendant, including inactive ones, in hierarchy order. The implementation does not filter by
tag. Disable autoFindCameras to maintain the cameras list manually.
currentCameraIndex selects the first active entry. It is clamped to the list before a camera is
activated, so an index left over from a shorter list no longer disables every camera.
Input and lifecycle
While the parent vehicle is enabled and locally owned, CameraChanger combines
SceneInputProviderBase.ChangeCamera() from the scene's registered input providers. A true result
calls NextCamera().
The component also responds to the parent Vehicle:
- vehicle enable: enable the current camera and disable the others;
- vehicle disable: disable every camera; and
- remote multiplayer status: disable every camera for a remote instance.
Public methods
NextCamera() and PreviousCamera() are the only public switching methods. Both wrap at the ends
of the list and update camera and listener active states.
using NWH.Common.Cameras;
using UnityEngine;
public sealed class CameraButtons : MonoBehaviour
{
[SerializeField] private CameraChanger cameraChanger;
public void Next()
{
cameraChanger.NextCamera();
}
public void Previous()
{
cameraChanger.PreviousCamera();
}
}
CameraChanger does not expose SetCamera, camera-change events, or a public enable/disable-all
method.
VehicleCamera
VehicleCamera is the base class that ships for vehicle-following camera implementations. It
contains a public Transform target and a virtual Awake() method.
When target is unassigned, Awake() looks for a parent Rigidbody and uses its Transform. A
custom camera can inherit the base and implement its own movement:
using NWH.Common.Cameras;
using UnityEngine;
public sealed class FixedOffsetVehicleCamera : VehicleCamera
{
public Vector3 localOffset = new(0f, 2f, -6f);
private void LateUpdate()
{
if (target == null)
{
return;
}
transform.position = target.TransformPoint(localOffset);
transform.LookAt(target);
}
}
Assign target explicitly when the camera is not below the target Rigidbody.
CameraMouseDrag
CameraMouseDrag derives from VehicleCamera and supports first-person or third-person
operation. It reads the combined camera rotation, panning, modifiers, and zoom values from
SceneInputProviderBase.
Setup:
- Add a
CameraandCameraMouseDragto the camera GameObject. - Place it below the target Rigidbody or assign
target. - Add an
InputSystemSceneInputProvider,InputManagerSceneInputProvider, or customSceneInputProviderBaseimplementation to the scene. - Configure
povTypeand rotation/panning settings. For third person, also configure distance and zoom.
Third-person-only options include auto-centering, speed-based field of view/distance/height, and look-ahead. Camera shake is available in both modes.
The scene provider controls whether rotation or panning requires its modifier button through
requireCameraRotationModifier and requireCameraPanningModifier.
CameraInsideVehicle
Add CameraInsideVehicle to a camera that should update the owning vehicle's interior-camera
state. This component also requires a Vehicle in its parent hierarchy.
While enabled it writes isInsideVehicle to Vehicle.CameraInsideVehicle every frame.
Whenever CameraChanger activates a camera - on vehicle enable, on a ChangeCamera() input, or
through a direct NextCamera() / PreviousCamera() call - it inspects the newly selected camera on
the following Update and treats a missing marker as outside. The marker on the active camera then
keeps writing that state each frame.
Because the flag is written every frame by whichever marker is active, add CameraInsideVehicle to
every camera in the rig and set isInsideVehicle to false on the exterior views. A camera with no
marker leaves the vehicle in the outside state.
Typical Setup
- Put a
CameraChangerbelow the vehicle root. - Create each camera as its child.
- Add
CameraMouseDragto cameras that need interactive movement. - Add
CameraInsideVehicleto every camera. SetisInsideVehicleto false on the exterior views. - Leave
autoFindCamerasenabled, or disable it and order thecameraslist manually. - Add one scene input provider for camera controls.
Use one active AudioListener per view. When the listener is on the same GameObject as a listed
camera, CameraChanger keeps its enabled state synchronized automatically.
Troubleshooting
CameraChanger reports that no parent Vehicle exists
Move it below a concrete component derived from NWH.Common.Vehicles.Vehicle. If only NWH Common
is installed, supply a project-defined subclass; the abstract Common Vehicle type cannot be
added directly.
No cameras were found
With autoFindCameras enabled, cameras must be descendants of the CameraChanger GameObject.
Otherwise disable automatic discovery and populate cameras.
Orbit input does nothing
Verify that a SceneInputProviderBase implementation is active and that its rotation modifier is
held, unless requireCameraRotationModifier is disabled.
A custom VehicleCamera has no target
Assign target or parent the camera below a Rigidbody before Awake.