UDN
Search public documentation:
CameraTechnicalGuide
日本語訳
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
UE3 Home > Gameplay Programming > Camera Technical Guide
Camera Technical Guide
Overview
Camera
- General
- PCOwner – Reference to the PlayerController which owns this camera.
- CameraStyle – Current camera mode for this camera. Used to determine the style of camera (i.e., first-person, third-person, free, etc.) when point of view is not being overridden by the view target.
- ViewTarget – Current data defining the view target. Type is TViewTarget.
- TViewTarget
- Target – Target actor that the camera is "following".
- Controller – Controller of the Target, if a Pawn.
- POV – Ideal point of view for the Target. Type is TPOV.
- TPOV
- Location – Location for the point of view.
- Rotation – Rotation of the point of view.
- FOV – Field of view angle for the point of view.
- AspectRatio – Aspect ratio to use for the Target.
- PRI – Player replication info used to track the same player through pawn transitions.
- TPOV
- FOV
- DefaultFOV – Default field of view for the camera.
- bLockedFOV – If True, the camera’s field of view will be locked to the value of LockedFOV.
- LockedFOV – Field of view to use when FOV is locked.
- Aspect Ratio
- DefaultAspectRatio – Default aspect ratio for the camera.
- bConstrainAspectRatio – If True, the camera’s aspect ratio will be constrained to the value of ConstrainedAspectRatio.
- ConstrainedAspectRatio – Aspect ratio to use when the aspect ratio of the camera is being constrained.
- General
- UpdateCamera [DeltaTime] – Called once per frame to perform an update of the camera.
- DeltaTime – The amount of time since the last update occurred.
- GetCameraViewPoint [OutCamLoc] [OutCamRot] – Retrieves the camera’s location and rotation. This function should not be called directly. Instead, the GetPlayerViewPoint() function of the PCOwner should be called instead.
- OutCamLoc – Outputs the camera’s location.
- OutCamRot – Outputs the camera’s rotation.
- ProcessViewRotation [DeltaTime] [OutViewRotation] [OutDeltaRot] – Called by the PCOwner to give the camera an opportunity to alter this frame's view rotation changes.
- DeltaTime – The amount of time since the last update occurred.
- OutViewRotation – Outputs the adjusted view rotation of the camera.
- OutDeltaRot – Outputs the adjusted delta rotation of the camera.
- UpdateCamera [DeltaTime] – Called once per frame to perform an update of the camera.
- FOV
- GetFOVAngle – Returns the camera’s current field of view angle.
- SetFOV [NewFOV] – Sets the camera’s field of view to the NewFOV value.
- NewFOV – Value to set the camera’s field of view to.
- View Target
- SetViewTarget [NewViewTarget] [TransitionParams] – Sets the view target of the camera.
- NewViewTarget – Actor to set as the new view target of the camera.
- TransitionParams – Blending parameters to use when transitioning to the new view target.
- UpdateViewTarget [OutVT] [DeltaTime] – Called per-frame to update the view target to it's new position, rotation, and fov. If using custom cameras (as opposed to overriding CalcCamera() in the view target actor), this is the key function to override to implement your desired behavior.
- OutVT – Outputs a data structure holding the view target and point of view of the camera.
- DeltaTime – The amount of time since the last update occurred.
- SetViewTarget [NewViewTarget] [TransitionParams] – Sets the view target of the camera.
Post Process Effects
Post process effects are effects applied to the rendered scene before it is displayed to the player. Each camera has the ability to apply its own set of post process settings that can override the world, volume, or default post process settings. For more information on post process effects, see PostProcessEditorUserGuide and PostProcessTechnicalGuide and PostProcessMaterials. Post Process Effects Properties- CameOverridePostProcessAlpha – Sets the influence of the camera’s post process settings with respect to the world, volume, or default post process settings. A value of 0.0 means the world, volume, or default post process has full influence. A value of 1.0 means the camera’s post process has full influence.
- CamPostProcessSettings – The post process settings to use when the camera is overriding the world, volume, or default post process.
- bEnableColorScaling – If True, color channels in the final image will be scaled using the ColorScale values.
- ColorScale – Vector for scaling individual color channels in final image.
- bEnableColorScaleInterp – If True, the camera will interpolate between color scaling values when new color scaling values are set through the SetDesiredColorScale() function.
- bEnableFading – If True, the camera will apply the FadeAmount of the FadeColor to the screen.
- FadeColor – Color to apply to the screen when the camera is fading.
- FadeAmount – Amount of fading to apply. In essence, the alpha of the fade.
- SetDesiredColorScale [NewColorScale] [InterpTime] – Sets new color scaling values and optionally interpolates depending on the value of bEnableColorScaleInterp.
- NewColorScale – New values to use for color scaling.
- InterpTime – Amount of time to take to interpolate to the new color scaling values.
Lens Effects
Lens effects are particle effects that are applied to the lens of the player’s camera. These lens effects can be used to create things like rain dripping down the camera lens, blood splatter, dirt or dust on the lens, etc. The camera class contains functions for applying these types of effects. For more information on particle systems and effects, see ParticleSystemReference. Lens Effects Properties-
- CameraLensEffects – Array of all particle effects currently applied to the camera.
- FindCameraLensEffect [LensEffectEmitterClass] – Searches the lens effects applied to the camera currently and returns any of the matching type.
- LensEffectEmitterType – Class of lens effect to search for.
- AddCameraLensEffect [LensEffectEmitterClass] – Applies a new lens effect of the given type to the camera.
- LensEffectEmitterClass – Class of lens effect to apply to the camera.
- RemoveCameraLensEffect [Emitter] – Removes a lens effect from the camera.
- Emitter – Lens effect to remove from the camera.
- ClearCameraLensEffects – Removes all lens effects currently applied to the camera.
Camera Animations
Camera animations are animations that can be created within Matinee (or optionally in an external animation editor and imported) that use the translation and rotation information of the animation to offset the camera during play. They also provide the ability to animate any of the other properties of the camera that can normally be animated in Matinee, such as FOV or postprocess effects. This can be quite useful for creating effects like camera shaking, the hand-bobbing of a handheld camera, or any other animation effect. For more information on setting up camera animations, see SettingUpCameras. Camera Animation Functions- PlayCameraAnim [CameraAnim] [Rate] [Scale] [BlendInTime] [BlendOutTime] [bLoop] [bRandomStartTime] [Duration] [bSingleInstance] – Plays a camera animation on the camera.
- CameraAnim – Camera animation to play.
- Rate – Optional. Speed at which to play the camera animation.
- Scale – Optional. Intensity multiplier to apply to the camera animation transformations.
- BlendInTime – Optional. Amount of time to take to blend into the camera animation.
- BlendOutTime – Optional. Amount of time to take to blend out of the camera animation.
- bLoop – Optional. If True, the camera animation will continue to loop until explicitly stopped.
- bRandomStartTime – Optional. If True, the camera animation will begin playing at a random time within the animation’s timeline.
- Duration – Optional. Amount of time to play the animation for. If not set, the entire animation will be played.
- bSingleInstance – Optional. If True, only one instance of the camera shake will be allowed to exist at any one time.
- StopAllCameraAnims [bImmediate] – Stops all camera animations currently playing.
- bImmediate – Optional. If True, the animations will stop immediately, ignoring any blending times set.
- StopAllCameraAnimsByType [Anim] [bImmediate] – Stops all instances of a specific type of camera animation.
- Anim – The type of camera animation to stop.
- bImmediate – Optional. If True, the animations will stop immediately, ignoring any blending times set.
- StopCameraAnim [AnimInst] [bImmediate] – Stops a specific instance of a camera animation.
- AnimInst – The camera animation instance to stop.
- bImmediate – Optional. If True, the animations will stop immediately, ignoring any blending times set.
Camera Modifiers
Camera modifiers are objects which, when applied to a camera, can modify properties of the camera. The CameraModifier class is the base class for these effects. By subclassing this class and overriding functions within it, completely custom modifiers can be created. The CameraModifier_CameraShake class is a good example of what can be accomplished with camera modifiers. Camera Modifier Properties-
- ModifierList – Array of all camera modifiers currently applied to the camera
- CameraShakeModClass – Class to use for cone-driven camera shake, i.e. non-camera animation screen shake from Kismet.
- PlayCameraShake [Shake] [Scale] [PlaySpace] [UserPlaySpaceRot] – Plays a camera shake effect on the camera.
- Shake – CamerShake settings to use for the camera shake effect.
- Scale – Scaling factor to multiply the camera shake settings by.
- PlaySpace – Optional. Play space to use for the camera shake.
- UserPlaySpaceRot – Optional. Rotation to use for user-defined play spaces.
- StopCameraShake [Shake] – Stops playing a camera shake effect on the camera.
- Shake – The camera shake to stop playing.
- CalcRadialCameraShake [Cam] [Epicenter] [InnerRadius] [OuterRadius] [Falloff] – Calculates and returns the intensity for a particular camera of a radial shake.
- Cam – Camera to calculate the intensity for.
- Epicenter – Location where the camera shake originates from.
- InnerRadius – Distance from the epicenter where falloff begins.
- OuterRadius – Distance from epicenter where the effect of the camera shake ends.
- Falloff – Exponent to use for calculating the falloff of the intensity.
- PlayWorldCameraShake [Shake] [ShakeInstigator] [Epicenter] [InnerRadius] [OuterRadius] [Falloff] [bTrForceFeedback] [bOrientShakeTowardEpicenter] – Plays an in-world camera shake that affects all nearby cameras.
- Shake – camera shake to play.
- ShakeInstigator – Actor that instigated the camera shake.
- Epicenter – Location where the camera shake originates from.
- InnerRadius – Distance from the epicenter where falloff begins.
- OuterRadius – Distance from epicenter where the effect of the camera shake ends.
- Falloff – Exponent to use for calculating the falloff of the intensity.
- bTryForceFeedback – If true, force feedback will attempt to be applied to any controllers being affected.
- bOrientShakeTowardEpicenter – Optional. If True, any offsets in the camera shake will be applied relative to facing the epicenter, with the positive X-axis being towards the epicenter.
- ClearAllCameraShakes – Removes all camera shakes currently applied to the camera.
Player Controller
- PlayerCamera – Reference to the player’s camera.
- CameraClass – Class of camera to use for the player.
- ViewTarget – The current view target of the player’s camera.
- RealViewTarget – Player replication info of the view target of the player’s camera.
- FOVangle – Field of view angle of the Player’s camera.
- DefaultFOV – Default field of view angle to use for the player’s camera.
- GetPlayerViewPoint [out_Location] [out_Rotation] – This returns the point of view of the Controller’s Pawn. For human players, this is the camera’s viewpoint. For AI-controlled players, this is the viewpoint from the Pawn’s eyes. In this base implementation, it is simply the location and rotation of the Controller itself.
- out_Location – Outputs the location of the player’s viewpoint.
- out_Rotation – Outputs the rotation of the player’s viewpoint.
- GetActorEyesViewPoint [out_Location] [out_Rotation] – This returns the point of view of the Controller or its Pawn if one exists. Essentially, this returns where the player is looking from and in which direction.
- out_Location – Outputs the location of the player’s eyes.
- out_Rotation – Outputs the rotation of the player’s eyes.
- UpdateRotation [DeltaTime] – This updates the rotation of the Controller and that of the Controller’s Pawn based on the player’s input.
- DeltaTime – The amount of time since the last update occurred.
- ProcessViewRotation [DeltaTime] [out_ViewRotation] [DeltaRot] – This is called to allow for any modifications to be made to the controller's view rotation (e.g. clamping). This is called from UpdateRotation().
- DeltaTime – The amount of time since the last update occurred.
- out_ViewRotation – Outputs the player’s view rotation.
- DeltaRot – Change in rotation due to player input.
- PlayerMove [DeltaTime] – This calculates the new acceleration and rotation values for the current move and then calls either ProcessMove() (for single-player or listen servers) or ReplicateMove() (for network clients). This is simply a stub in the base PlayerController class but is overridden within certain states which involve movement, such as the PlayerWalking state. This function is called from the PlayerTick() function every cycle.
- ProcessMove [DeltaTime] [newAccel] [DoubleClickMove] [DeltaRot] – This handles the current move on the client. This function is overridden inside certain states which require special functionality for movement.
Pawn
- CalcCamera [DeltaTime] [out_CamLoc] [out_CamRot] [out_FOV] – This calculates the camera’s viewpoint when viewing from the Pawn. This is the main camera calculation for the player.
- DeltaTime – The amount of time since the last update occurred.
- out_CamLoc – Outputs the camera’s location.
- out_CamRot – Outputs the camera’s rotation.
- out_FOV – Outputs the camera’s field of view.
- GetDefaultCameraMode [RequestedBy] – This returns the default camera mode, as a name, that should be used for this Pawn. This is usually called by the controller when possessing the Pawn.
- RequestedBy - The controller requesting the default camera mode.
- ProcessViewRotation [deltaTime] [out_ViewRotation] [out_DeltaRot] – This gives the pawn the opportunity to influence the player’s view rotation and returns the final view rotation as the out_ViewRotation parameter. This is called from the UpdateRotation() function of the PlayerController.
- deltaTime – The amount of time since the last update occurred.
- out_ViewRotation – Outputs the rotation of the Pawn’s point of view.
- out_DeltaRot – Outputs the delta rotation.
- SetViewRotation [NewRotation] – Sets the rotation of the Controller, if one exists, or of the Pawn itself if no Controller exists.
- NewRotation – New rotation to set the Pawn’s view to.
- GetActorEyesViewPoint [out_Location] [out_Rotation] – This returns the location and orientation of the Pawn’s eyes, or the point of view of the player. For a first person perspective this is identical to the camera location and orientation. It is also the view point most traces will be performed from.
- out_Location – Outputs the location of the Pawn’s eyes.
- out_Rotation – Outputs the rotation of the Pawn’s eyes.
Customizing Camera Behavior
Examples - CalcCamera
class UDNGame extends UTDeathMatch; defaultproperties { DefaultPawnClass=class'UDNExamples.UDNPawn' PlayerControllerClass=class'UDNExamples.UDNPlayerController' MapPrefixes[0]="UDN" }
[Engine.GameInfo] DefaultGame=UDNExamples.UDNGame DefaultServerGame=UDNExamples.UDNGame
Example First Person Camera
A first person perspective is the default camera type for all pawns extending from UTPawn. This example pulls out the main parts that make up that camera type from each class involved and places them in new subclasses in order to better demonstrate the process involved in creating a basic first person camera.
class UDNPawn extends UTPawn; simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { // Calculate first person camera position and rotation GetActorEyesViewPoint( out_CamLoc, out_CamRot ); return true; } defaultproperties { }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { ignores SeePlayer, HearNoise, Bump; function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if( Pawn == None ) { return; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } Pawn.Acceleration = NewAccel; CheckJumpOrDuck(); } } function UpdateRotation( float DeltaTime ) { local Rotator DeltaRot, newRotation, ViewRotation; ViewRotation = Rotation; if (Pawn!=none) { Pawn.SetDesiredRotation(ViewRotation); } // Calculate Delta to be applied on ViewRotation DeltaRot.Yaw = PlayerInput.aTurn; DeltaRot.Pitch = PlayerInput.aLookUp; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); NewRotation = ViewRotation; NewRotation.Roll = Rotation.Roll; if ( Pawn != None ) Pawn.FaceRotation(NewRotation, deltatime); } defaultproperties { }
Example Third Person Camera
A third person camera setup is also included as an alternate camera type for all subclasses of UTPawn. This example pulls the main parts out and overrides the default camera to be this third person camera.
class UDNPawn extends UTPawn; //override to make player mesh visible by default simulated event BecomeViewTarget( PlayerController PC ) { local UTPlayerController UTPC; Super.BecomeViewTarget(PC); if (LocalPlayer(PC.Player) != None) { UTPC = UTPlayerController(PC); if (UTPC != None) { //set player controller to behind view and make mesh visible UTPC.SetBehindView(true); SetMeshVisibility(UTPC.bBehindView); } } } simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { local vector CamStart, HitLocation, HitNormal, CamDirX, CamDirY, CamDirZ, CurrentCamOffset; local float DesiredCameraZOffset; CamStart = Location; CurrentCamOffset = CamOffset; DesiredCameraZOffset = (Health > 0) ? 1.2 * GetCollisionHeight() + Mesh.Translation.Z : 0.f; CameraZOffset = (fDeltaTime < 0.2) ? DesiredCameraZOffset * 5 * fDeltaTime + (1 - 5*fDeltaTime) * CameraZOffset : DesiredCameraZOffset; if ( Health <= 0 ) { CurrentCamOffset = vect(0,0,0); CurrentCamOffset.X = GetCollisionRadius(); } CamStart.Z += CameraZOffset; GetAxes(out_CamRot, CamDirX, CamDirY, CamDirZ); CamDirX *= CurrentCameraScale; if ( (Health <= 0) || bFeigningDeath ) { // adjust camera position to make sure it's not clipping into world // @todo fixmesteve. Note that you can still get clipping if FindSpot fails (happens rarely) FindSpot(GetCollisionExtent(),CamStart); } if (CurrentCameraScale < CameraScale) { CurrentCameraScale = FMin(CameraScale, CurrentCameraScale + 5 * FMax(CameraScale - CurrentCameraScale, 0.3)*fDeltaTime); } else if (CurrentCameraScale > CameraScale) { CurrentCameraScale = FMax(CameraScale, CurrentCameraScale - 5 * FMax(CameraScale - CurrentCameraScale, 0.3)*fDeltaTime); } if (CamDirX.Z > GetCollisionHeight()) { CamDirX *= square(cos(out_CamRot.Pitch * 0.0000958738)); // 0.0000958738 = 2*PI/65536 } out_CamLoc = CamStart - CamDirX*CurrentCamOffset.X + CurrentCamOffset.Y*CamDirY + CurrentCamOffset.Z*CamDirZ; if (Trace(HitLocation, HitNormal, out_CamLoc, CamStart, false, vect(12,12,12)) != None) { out_CamLoc = HitLocation; } return true; } defaultproperties { }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { ignores SeePlayer, HearNoise, Bump; function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if( Pawn == None ) { return; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } Pawn.Acceleration = NewAccel; CheckJumpOrDuck(); } } function UpdateRotation( float DeltaTime ) { local Rotator DeltaRot, newRotation, ViewRotation; ViewRotation = Rotation; if (Pawn!=none) { Pawn.SetDesiredRotation(ViewRotation); } // Calculate Delta to be applied on ViewRotation DeltaRot.Yaw = PlayerInput.aTurn; DeltaRot.Pitch = PlayerInput.aLookUp; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); NewRotation = ViewRotation; NewRotation.Roll = Rotation.Roll; if ( Pawn != None ) Pawn.FaceRotation(NewRotation, deltatime); } defaultproperties { }
Example Top-Down Camera
A top-down camera can be created by making some additional modifications. It is similar to the third-person camera setup, but also requires limiting the Pawn’s rotation, specifically its pitch as aiming up or down won’t be allowed.
class UDNPawn extends UTPawn; var float CamOffsetDistance; //distance to offset the camera above the player var bool bFollowPlayerRotation; //If true, camera rotates with player //override to make player mesh visible by default simulated event BecomeViewTarget( PlayerController PC ) { local UTPlayerController UTPC; Super.BecomeViewTarget(PC); if (LocalPlayer(PC.Player) != None) { UTPC = UTPlayerController(PC); if (UTPC != None) { //set player controller to behind view and make mesh visible UTPC.SetBehindView(true); SetMeshVisibility(UTPC.bBehindView); UTPC.bNoCrosshair = true; } } } simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.Z += CamOffsetDistance; if(!bFollowPlayerRotation) { out_CamRot.Pitch = -16384; out_CamRot.Yaw = 0; out_CamRot.Roll = 0; } else { out_CamRot.Pitch = -16384; out_CamRot.Yaw = Rotation.Yaw; out_CamRot.Roll = 0; } return true; } simulated singular event Rotator GetBaseAimRotation() { local rotator POVRot, tempRot; tempRot = Rotation; tempRot.Pitch = 0; SetRotation(tempRot); POVRot = Rotation; POVRot.Pitch = 0; return POVRot; } defaultproperties { bFollowPlayerRotation = false; CamOffsetDistance=384.0 }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { ignores SeePlayer, HearNoise, Bump; function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if( Pawn == None ) { return; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } Pawn.Acceleration = NewAccel; CheckJumpOrDuck(); } } function UpdateRotation( float DeltaTime ) { local Rotator DeltaRot, newRotation, ViewRotation; ViewRotation = Rotation; if (Pawn!=none) { Pawn.SetDesiredRotation(ViewRotation); } // Calculate Delta to be applied on ViewRotation DeltaRot.Yaw = PlayerInput.aTurn; DeltaRot.Pitch = 0; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); NewRotation = ViewRotation; NewRotation.Roll = Rotation.Roll; if ( Pawn != None ) Pawn.FaceRotation(NewRotation, deltatime); } defaultproperties { }
Example Isometric Camera
A simple isometric-style camera is very similar to the top-down camera example shown previously. The camera is offset along two axes, X and Z, and then the pitch is rotated down to focus on the player.
class UDNPawn extends UTPawn; var float CamOffsetDistance; //distance to offset the camera from the player var int IsoCamAngle; //pitch angle of the camera //override to make player mesh visible by default simulated event BecomeViewTarget( PlayerController PC ) { local UTPlayerController UTPC; Super.BecomeViewTarget(PC); if (LocalPlayer(PC.Player) != None) { UTPC = UTPlayerController(PC); if (UTPC != None) { //set player controller to behind view and make mesh visible UTPC.SetBehindView(true); SetMeshVisibility(UTPC.bBehindView); UTPC.bNoCrosshair = true; } } } simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.X -= Cos(IsoCamAngle * UnrRotToRad) * CamOffsetDistance; out_CamLoc.Z += Sin(IsoCamAngle * UnrRotToRad) * CamOffsetDistance; out_CamRot.Pitch = -1 * IsoCamAngle; out_CamRot.Yaw = 0; out_CamRot.Roll = 0; return true; } simulated singular event Rotator GetBaseAimRotation() { local rotator POVRot, tempRot; tempRot = Rotation; tempRot.Pitch = 0; SetRotation(tempRot); POVRot = Rotation; POVRot.Pitch = 0; return POVRot; } defaultproperties { IsoCamAngle=6420 //35.264 degrees CamOffsetDistance=384.0 }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { ignores SeePlayer, HearNoise, Bump; function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if( Pawn == None ) { return; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } Pawn.Acceleration = NewAccel; CheckJumpOrDuck(); } } function UpdateRotation( float DeltaTime ) { local Rotator DeltaRot, newRotation, ViewRotation; ViewRotation = Rotation; if (Pawn!=none) { Pawn.SetDesiredRotation(ViewRotation); } // Calculate Delta to be applied on ViewRotation DeltaRot.Yaw = PlayerInput.aTurn; DeltaRot.Pitch = 0; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); NewRotation = ViewRotation; NewRotation.Roll = Rotation.Roll; if ( Pawn != None ) Pawn.FaceRotation(NewRotation, deltatime); } defaultproperties { }
Example Side-Scrolling Camera
A simple side-scroller camera requires not only controlling the camera’s point of view, but also modifying the way player input is handled. The player is only allowed to move left and right on the screen and is always forced to face the direction they are moving. The input is required so that the A and D keys move the player forward or backward.
class UDNPawn extends UTPawn; var float CamOffsetDistance; //Position on Y-axis to lock camera to //override to make player mesh visible by default simulated event BecomeViewTarget( PlayerController PC ) { local UTPlayerController UTPC; Super.BecomeViewTarget(PC); if (LocalPlayer(PC.Player) != None) { UTPC = UTPlayerController(PC); if (UTPC != None) { //set player controller to behind view and make mesh visible UTPC.SetBehindView(true); SetMeshVisibility(UTPC.bBehindView); UTPC.bNoCrosshair = true; } } } simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.Y = CamOffsetDistance; out_CamRot.Pitch = 0; out_CamRot.Yaw = 16384; out_CamRot.Roll = 0; return true; } simulated singular event Rotator GetBaseAimRotation() { local rotator POVRot; POVRot = Rotation; if( (Rotation.Yaw % 65535 > 16384 && Rotation.Yaw % 65535 < 49560) || (Rotation.Yaw % 65535 < -16384 && Rotation.Yaw % 65535 > -49560) ) { POVRot.Yaw = 32768; } else { POVRot.Yaw = 0; } if( POVRot.Pitch == 0 ) { POVRot.Pitch = RemoteViewPitch << 8; } return POVRot; } defaultproperties { CamOffsetDistance=0.0 }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { ignores SeePlayer, HearNoise, Bump; function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { local Rotator tempRot; if( Pawn == None ) { return; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } Pawn.Acceleration.X = -1 * PlayerInput.aStrafe * DeltaTime * 100 * PlayerInput.MoveForwardSpeed; Pawn.Acceleration.Y = 0; Pawn.Acceleration.Z = 0; tempRot.Pitch = Pawn.Rotation.Pitch; tempRot.Roll = 0; if(Normal(Pawn.Acceleration) Dot Vect(1,0,0) > 0) { tempRot.Yaw = 0; Pawn.SetRotation(tempRot); } else if(Normal(Pawn.Acceleration) Dot Vect(1,0,0) < 0) { tempRot.Yaw = 32768; Pawn.SetRotation(tempRot); } CheckJumpOrDuck(); } } function UpdateRotation( float DeltaTime ) { local Rotator DeltaRot, ViewRotation; ViewRotation = Rotation; // Calculate Delta to be applied on ViewRotation DeltaRot.Yaw = Pawn.Rotation.Yaw; DeltaRot.Pitch = PlayerInput.aLookUp; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); } defaultproperties { }
Example All-In-One Camera
This example puts together all the other examples into a single implementation that allows the player to switch between any of the camera types and adjust them through the use of exec functions. UDNPawn.ucclass UDNPawn extends UTPawn; Enum CameraPerspective { CAM_FirstPerson, CAM_ThirdPerson, CAM_TopDown, CAM_SideScroller, CAM_Isometric }; var bool bFollowPlayerRotation; var CameraPerspective CameraType; var float CamOffsetDistance; var int IsoCamAngle; exec function CameraMode(CameraPerspective mode) { local UTPlayerController UTPC; CameraType = mode; UTPC = UTPlayerController(Controller); if (UTPC != None) { if(CameraType != CAM_FirstPerson) { UTPC.SetBehindView(true); if(CameraType != CAM_ThirdPerson) { UTPC.bNoCrosshair = true; } else { UTPC.bNoCrosshair = false; } } else { UTPC.bNoCrosshair = false; UTPC.SetBehindView(false); } SetMeshVisibility(UTPC.bBehindView); } } exec function IsoAngle(int angle) { IsoCamAngle = angle; } /* BecomeViewTarget Called by Camera when this actor becomes its ViewTarget */ simulated event BecomeViewTarget( PlayerController PC ) { local UTPlayerController UTPC; Super.BecomeViewTarget(PC); if (LocalPlayer(PC.Player) != None) { UTPC = UTPlayerController(PC); if (UTPC != None) { if(CameraType != CAM_FirstPerson) { UTPC.SetBehindView(true); if(CameraType != CAM_ThirdPerson) { UTPC.bNoCrosshair = true; } else { UTPC.bNoCrosshair = false; } } else { UTPC.bNoCrosshair = false; UTPC.SetBehindView(false); } SetMeshVisibility(UTPC.bBehindView); } } } /** * Calculate camera view point, when viewing this pawn. * * @param fDeltaTime delta time seconds since last update * @param out_CamLoc Camera Location * @param out_CamRot Camera Rotation * @param out_FOV Field of View * * @return true if Pawn should provide the camera point of view. */ simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { // Handle the fixed camera if (bFixedView) { out_CamLoc = FixedViewLoc; out_CamRot = FixedViewRot; } else { if ( CameraType == CAM_ThirdPerson ) // Handle BehindView { CalcThirdPersonCam(fDeltaTime, out_CamLoc, out_CamRot, out_FOV); } else if ( CameraType == CAM_TopDown ) // Handle BehindView { CalcTopDownCam(fDeltaTime, out_CamLoc, out_CamRot, out_FOV); } else if ( CameraType == CAM_SideScroller ) // Handle BehindView { CalcSideScrollerCam(fDeltaTime, out_CamLoc, out_CamRot, out_FOV); } else if ( CameraType == CAM_Isometric ) // Handle BehindView { CalcIsometricCam(fDeltaTime, out_CamLoc, out_CamRot, out_FOV); } else { // By default, we view through the Pawn's eyes.. GetActorEyesViewPoint( out_CamLoc, out_CamRot ); } if ( UTWeapon(Weapon) != none) { UTWeapon(Weapon).WeaponCalcCamera(fDeltaTime, out_CamLoc, out_CamRot); } } return true; } simulated function bool CalcTopDownCam( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.Z += CamOffsetDistance; if(!bFollowPlayerRotation) { out_CamRot.Pitch = -16384; out_CamRot.Yaw = 0; out_CamRot.Roll = 0; } else { out_CamRot.Pitch = -16384; out_CamRot.Yaw = Rotation.Yaw; out_CamRot.Roll = 0; } return true; } simulated function bool CalcSideScrollerCam( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.Y = CamOffsetDistance; out_CamRot.Pitch = 0; out_CamRot.Yaw = 16384; out_CamRot.Roll = 0; return true; } simulated function bool CalcIsometricCam( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { out_CamLoc = Location; out_CamLoc.X -= Cos(IsoCamAngle * UnrRotToRad) * CamOffsetDistance; out_CamLoc.Z += Sin(IsoCamAngle * UnrRotToRad) * CamOffsetDistance; out_CamRot.Pitch = -1 * IsoCamAngle; out_CamRot.Yaw = 0; out_CamRot.Roll = 0; return true; } /** * returns base Aim Rotation without any adjustment (no aim error, no autolock, no adhesion.. just clean initial aim rotation!) * * @return base Aim rotation. */ simulated singular event Rotator GetBaseAimRotation() { local vector POVLoc; local rotator POVRot, tempRot; if(CameraType == CAM_TopDown || CameraType == CAM_Isometric) { tempRot = Rotation; tempRot.Pitch = 0; SetRotation(tempRot); POVRot = Rotation; POVRot.Pitch = 0; } else if(CameraType == CAM_SideScroller) { POVRot = Rotation; if( (Rotation.Yaw % 65535 > 16384 && Rotation.Yaw % 65535 < 49560) || (Rotation.Yaw % 65535 < -16384 && Rotation.Yaw % 65535 > -49560) ) { POVRot.Yaw = 32768; } else { POVRot.Yaw = 0; } if( POVRot.Pitch == 0 ) { POVRot.Pitch = RemoteViewPitch << 8; } } else { if( Controller != None && !InFreeCam() ) { Controller.GetPlayerViewPoint(POVLoc, POVRot); return POVRot; } else { POVRot = Rotation; if( POVRot.Pitch == 0 ) { POVRot.Pitch = RemoteViewPitch << 8; } } } return POVRot; } defaultproperties { CameraType=CAM_FirstPerson; bFollowPlayerRotation = false; CamOffsetDistance=384.0 IsoCamAngle=6420 //35.264 degrees }
class UDNPlayerController extends UTPlayerController; state PlayerWalking { function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { local UDNPawn P; local Rotator tempRot; if( (Pawn != None) ) { P = UDNPawn(Pawn); if(P != none) { if(P.CameraType == CAM_SideScroller) { Pawn.Acceleration.X = -1 * PlayerInput.aStrafe * DeltaTime * 100 * PlayerInput.MoveForwardSpeed; Pawn.Acceleration.Y = 0; Pawn.Acceleration.Z = 0; tempRot.Pitch = P.Rotation.Pitch; tempRot.Roll = 0; if(Normal(Pawn.Acceleration) Dot Vect(1,0,0) > 0) { tempRot.Yaw = 0; P.SetRotation(tempRot); } else if(Normal(Pawn.Acceleration) Dot Vect(1,0,0) < 0) { tempRot.Yaw = 32768; P.SetRotation(tempRot); } } else { if ( (DoubleClickMove == DCLICK_Active) && (Pawn.Physics == PHYS_Falling) ) DoubleClickDir = DCLICK_Active; else if ( (DoubleClickMove != DCLICK_None) && (DoubleClickMove < DCLICK_Active) ) { if ( UTPawn(Pawn).Dodge(DoubleClickMove) ) DoubleClickDir = DCLICK_Active; } Pawn.Acceleration = newAccel; } if (Role == ROLE_Authority) { // Update ViewPitch for remote clients Pawn.SetRemoteViewPitch( Rotation.Pitch ); } } CheckJumpOrDuck(); } } } function UpdateRotation( float DeltaTime ) { local UDNPawn P; local Rotator DeltaRot, newRotation, ViewRotation; P = UDNPawn(Pawn); ViewRotation = Rotation; if (p != none && P.CameraType != CAM_SideScroller) { Pawn.SetDesiredRotation(ViewRotation); } // Calculate Delta to be applied on ViewRotation if( P != none && P.CameraType == CAM_SideScroller ) { DeltaRot.Yaw = Pawn.Rotation.Yaw; } else { DeltaRot.Yaw = PlayerInput.aTurn; } DeltaRot.Pitch = PlayerInput.aLookUp; ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); SetRotation(ViewRotation); ViewShake( deltaTime ); NewRotation = ViewRotation; NewRotation.Roll = Rotation.Roll; if (P != None && P.CameraType != CAM_SideScroller ) Pawn.FaceRotation(NewRotation, deltatime); } defaultproperties { }
Example - Custom Camera
Base Camera Module
The base camera module class extends from the Object class and defines all the properties and behavior that will be common to all camera modules. Its one property is a reference to the camera that owns it. Some initialization and deinitialization functions are defined, but the main functionality in this class is performed by the UpdateCamera() function which calculates the new location and rotation of the player's camera and can apply any other desired effects or modifications. This class is defined using the config(Camera) specifier so that any properties that should be configurable or persistent in the specific camera modules will be found in the *Camera.ini file. It is also defined as abstract so that it cannot actually be used. It is more like a template for the specific camera modules to build from and not a class that would ever actually be used itself. UDNCameraModule.ucclass UDNCameraModule extends Object abstract config(Camera); //owning camera var transient UDNPlayerCamera PlayerCamera; //mode-specific initialization function Init(); /** Called when the camera becomes active */ function OnBecomeActive( UDNCameraModule OldCamera ); /** Called when the camera becomes inactive */ function OnBecomeInActive( UDNCameraModule NewCamera ); //Calculate new camera location and rotation function UpdateCamera(Pawn P, UDNPlayerCamera CameraActor, float DeltaTime, out TViewTarget OutVT); //initialize new view target simulated function BecomeViewTarget( UDNPlayerController PC ); //handle zooming in function ZoomIn(); //handle zooming in function ZoomOut(); defaultproperties { }
Custom Camera
The new camera class extends from the base Camera class, overriding some functions and adding new functionality to handle the camera modules. The camera's main job in this system is to act as the middleman for the camera module as it is now handling the majority of the calculations. UDNPlayerCamera.ucclass UDNPlayerCamera extends Camera config(Camera); var UDNPlayerController PlayerOwner; //player controller owning this camera var UDNCameraModule CurrentCamera; //Current camera mode in use var config string DefaultCameraClass; //class for default camera mdoe function PostBeginPlay() { local class<UDNCameraModule> NewClass; Super.PostBeginPlay(); // Setup camera mode if ( (CurrentCamera == None) && (DefaultCameraClass != "") ) { //get the default camera class to use NewClass = class<UDNCameraModule>( DynamicLoadObject( DefaultCameraClass, class'Class' ) ); //create default camera CurrentCamera = CreateCamera(NewClass); } } //Initialize the PlayerCamera for the owning PlayerController function InitializeFor(PlayerController PC) { //do parent initialization Super.InitializeFor(PC); //set PlayerOwner to player controller PlayerOwner = UDNPlayerController(PC); } /** * Internal. Creates and initializes a new camera of the specified class, returns the object ref. */ function UDNCameraModule CreateCamera(class<UDNCameraModule> CameraClass) { local UDNCameraModule NewCam; //create new camera and initialize NewCam = new(Outer) CameraClass; NewCam.PlayerCamera = self; NewCam.Init(); //call active/inactive functions on new/old cameras if(CurrentCamera != none) { CurrentCamera.OnBecomeInactive(NewCam); NewCam.OnBecomeActive(CurrentCamera); } else { NewCam.OnBecomeActive(None); } //set new camera as current CurrentCamera = NewCam; return NewCam; } /** * Query ViewTarget and outputs Point Of View. * * @param OutVT ViewTarget to use. * @param DeltaTime Delta Time since last camera update (in seconds). */ function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime) { local CameraActor CamActor; local TPOV OrigPOV; local Vector Loc, Pos, HitLocation, HitNormal; local Rotator Rot; local Actor HitActor; // Don't update outgoing viewtarget during an interpolation if( PendingViewTarget.Target != None && OutVT == ViewTarget && BlendParams.bLockOutgoing ) { return; } OrigPOV = OutVT.POV; // Default FOV on viewtarget OutVT.POV.FOV = DefaultFOV; // Viewing through a camera actor. CamActor = CameraActor(OutVT.Target); if( CamActor != None ) { CamActor.GetCameraView(DeltaTime, OutVT.POV); // Grab aspect ratio from the CameraActor. bConstrainAspectRatio = bConstrainAspectRatio || CamActor.bConstrainAspectRatio; OutVT.AspectRatio = CamActor.AspectRatio; // See if the CameraActor wants to override the PostProcess settings used. CamOverridePostProcessAlpha = CamActor.CamOverridePostProcessAlpha; CamPostProcessSettings = CamActor.CamOverridePostProcess; } else { // Give Pawn Viewtarget a chance to dictate the camera position. // If Pawn doesn't override the camera view, then we proceed with our own defaults if( Pawn(OutVT.Target) == None || !Pawn(OutVT.Target).CalcCamera(DeltaTime, OutVT.POV.Location, OutVT.POV.Rotation, OutVT.POV.FOV) ) { //Pawn didn't want control and we have a custom mode if(CurrentCamera != none) { //allow mode to handle camera update CurrentCamera.UpdateCamera(Pawn(OutVT.Target), self, DeltaTime, OutVT); } //no custom mode - use default camera styles else { switch( CameraStyle ) { case 'Fixed' : // do not update, keep previous camera position by restoring // saved POV, in case CalcCamera changes it but still returns false OutVT.POV = OrigPOV; break; case 'ThirdPerson' : // Simple third person view implementation case 'FreeCam' : case 'FreeCam_Default': Loc = OutVT.Target.Location; Rot = OutVT.Target.Rotation; //OutVT.Target.GetActorEyesViewPoint(Loc, Rot); if( CameraStyle == 'FreeCam' || CameraStyle == 'FreeCam_Default' ) { Rot = PCOwner.Rotation; } Loc += FreeCamOffset >> Rot; Pos = Loc - Vector(Rot) * FreeCamDistance; // @fixme, respect BlockingVolume.bBlockCamera=false HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12)); OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation; OutVT.POV.Rotation = Rot; break; case 'FirstPerson' : // Simple first person, view through viewtarget's 'eyes' default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation); break; } } } } ApplyCameraModifiers(DeltaTime, OutVT.POV); // set camera's location and rotation, to handle cases where we are not locked to view target SetRotation(OutVT.POV.Rotation); SetLocation(OutVT.POV.Location); } //pass view target initialization through to camera mode simulated function BecomeViewTarget( PlayerController PC ) { CurrentCamera.BecomeViewTarget(UDNPlayerController(PC)); } //pass zoom in through to camera mode function ZoomIn() { CurrentCamera.ZoomIn(); } //pass zoom out through to camera mode function ZoomOut() { CurrentCamera.ZoomOut(); } defaultproperties { }
Base Control Module
The base control module class extends from the Object class and defines all the properties and behavior that will be common to all control modules. It contains a reference to the controller that owns it as well as holding the current mouse cursor position. Like the base camera module, some initialization and deinitialization functions are defined which allow for any type-specific setup or cleanup that may be necessary. The rest of the class is made up of the functions that will handle the player movement and aiming as well. This class is defined using the config(Control) specifier so that any properties that should be configurable or persistent in the specific control modules will be found in the *Control.ini file. It is also defined as abstract so that it cannot actually be used. It nothing more than a template for the specific control modules to build from and not a class that would ever actually be used itself. UDNControlModule.ucclass UDNControlModule extends Object abstract config(Control); //reference to the owning controller var UDNPlayerController Controller; //mode-specific initialization function Init(); /** Called when the camera becomes active */ function OnBecomeActive( UDNControlModule OldModule ); /** Called when the camera becomes inactive */ function OnBecomeInActive( UDNControlModule NewModule ); //Calculate Pawn aim rotation simulated singular function Rotator GetBaseAimRotation(); //Handle custom player movement function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot); //Calculate controller rotation function UpdateRotation(float DeltaTime); defaultproperties { }
Engine Class Overrides
Several engine classes need to be extended to be able to interface with the new camera and control system, mainly the PlayerController, Pawn, and HUD classes. A new gametype will aslo be created ot make use of these new classesPlayerController
The new PlayerController class adds exec functions for changing the type of camera module being used as well as zooming in or out (how the zoom functions work is dependent on how the current camera module implements them). The ProcessMove() function of the PlayerWalking state and the UpdateRotation() functions are overridden to add calls to the control module. Finally, the GetPlayerViewPoint() function is overridden and modified to keep the camera from being destroyed and to force the PlayerController to use the new custom camera if it exists. UDNPlayerController.ucclass UDNPlayerController extends UTPlayerController; var UDNControlModule ControlModule; //player control module to use var config string DefaultControlModuleClass; //default class for player control module //exec function for switching to a different camera by class exec function ChangeControls( string ClassName ) { local class<UDNControlModule> ControlClass; local UDNControlModule NewControlModule; ControlClass = class<UDNControlModule>( DynamicLoadObject( DefaultControlModuleClass, class'Class' ) ); if(ControlClass != none) { // Associate module with PlayerController NewControlModule = new(Outer) ControlClass; NewControlModule.Controller = self; NewControlModule.Init(); //call active/inactive functions on new/old modules if(ControlModule != none) { ControlModule.OnBecomeInactive(NewControlModule); NewControlModule.OnBecomeActive(ControlModule); } else { NewControlModule.OnBecomeActive(None); } ControlModule = NewControlModule; } else { `log("Couldn't get control module class!"); // not having a Control Class is fine. PlayerController will use default controls. } } //exec function for switching to a different camera by class exec function ChangeCamera( string ClassName ) { local class<UDNCameraModule> NewClass; NewClass = class<UDNCameraModule>( DynamicLoadObject( ClassName, class'Class' ) ); if(NewClass != none && UDNPlayerCamera(PlayerCamera) != none) { UDNPlayerCamera(PlayerCamera).CreateCamera(NewClass); } } //zoom in exec exec function ZoomIn() { if(UDNPlayerCamera(PlayerCamera) != none) { UDNPlayerCamera(PlayerCamera).ZoomIn(); } } //zoom out exec exec function ZoomOut() { if(UDNPlayerCamera(PlayerCamera) != none) { UDNPlayerCamera(PlayerCamera).ZoomOut(); } } simulated function PostBeginPlay() { local class<UDNControlModule> ControlClass; local UDNControlModule NewControlModule; Super.PostBeginPlay(); ControlClass = class<UDNControlModule>( DynamicLoadObject( DefaultControlModuleClass, class'Class' ) ); if(ControlClass != none) { // Associate module with PlayerController NewControlModule = new(Outer) ControlClass; NewControlModule.Controller = self; NewControlModule.Init(); //call active/inactive functions on new/old modules if(ControlModule != none) { ControlModule.OnBecomeInactive(NewControlModule); NewControlModule.OnBecomeActive(ControlModule); } else { NewControlModule.OnBecomeActive(None); } ControlModule = NewControlModule; } else { `log("Couldn't get control module class!"); // not having a Control Class is fine. PlayerController will use default controls. } } state PlayerWalking { function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { //Controller has a UDNPlayerCamera if(ControlModule != none) { //allow custom camera to override player movement ControlModule.ProcessMove(DeltaTime, NewAccel, DoubleClickMove, DeltaRot); } else { Super.ProcessMove(DeltaTime, NewAccel, DoubleClickMove, DeltaRot); } } } function UpdateRotation( float DeltaTime ) { //Controller has a UDNPlayerCamera if(ControlModule != none) { //allow custom camera to update our rotation ControlModule.UpdateRotation(DeltaTime); } else { Super.UpdateRotation(DeltaTime); } } /* GetPlayerViewPoint: Returns Player's Point of View For the AI this means the Pawn's Eyes ViewPoint For a Human player, this means the Camera's ViewPoint */ simulated event GetPlayerViewPoint( out vector POVLocation, out Rotator POVRotation ) { local float DeltaTime; local UTPawn P; P = IsLocalPlayerController() ? UTPawn(CalcViewActor) : None; DeltaTime = WorldInfo.TimeSeconds - LastCameraTimeStamp; LastCameraTimeStamp = WorldInfo.TimeSeconds; // support for using CameraActor views if ( CameraActor(ViewTarget) != None ) { if ( PlayerCamera == None ) { super.ResetCameraMode(); SpawnCamera(); } super.GetPlayerViewPoint( POVLocation, POVRotation ); } else { //do not destroy our camera!!! /* if ( PlayerCamera != None ) { PlayerCamera.Destroy(); PlayerCamera = None; } */ //no camera, we have view target - let view target be in control if ( PlayerCamera == None && ViewTarget != None ) { POVRotation = Rotation; if ( (PlayerReplicationInfo != None) && PlayerReplicationInfo.bOnlySpectator && (UTVehicle(ViewTarget) != None) ) { UTVehicle(ViewTarget).bSpectatedView = true; ViewTarget.CalcCamera( DeltaTime, POVLocation, POVRotation, FOVAngle ); UTVehicle(ViewTarget).bSpectatedView = false; } else { ViewTarget.CalcCamera( DeltaTime, POVLocation, POVRotation, FOVAngle ); } if ( bFreeCamera ) { POVRotation = Rotation; } } //no camera, no view target - we are in control else if(PlayerCamera == None) { CalcCamera( DeltaTime, POVLocation, POVRotation, FOVAngle ); return; } //we have a camera - let camera be in control else { POVLocation = PlayerCamera.ViewTarget.POV.Location; POVRotation = PlayerCamera.ViewTarget.POV.Rotation; FOVAngle = PlayerCamera.ViewTarget.POV.FOV; } } // apply view shake POVRotation = Normalize(POVRotation + ShakeRot); POVLocation += ShakeOffset >> Rotation; if( CameraEffect != none ) { CameraEffect.UpdateLocation(POVLocation, POVRotation, GetFOVAngle()); } // cache result CalcViewActor = ViewTarget; CalcViewActorLocation = ViewTarget.Location; CalcViewActorRotation = ViewTarget.Rotation; CalcViewLocation = POVLocation; CalcViewRotation = POVRotation; if ( P != None ) { CalcEyeHeight = P.EyeHeight; CalcWalkBob = P.WalkBob; } } defaultproperties { CameraClass=class'UDNExamples.UDNPlayerCamera' MatineeCameraClass=class'UDNExamples.UDNPlayerCamera' }
Pawn Class
The new Pawn class overrides the CalcCamera() function to simply return false, allowing the new camera system to always control the camera location and position. The BecomeViewTarget() and GetBaseAimRotation() functions are overridden to pass the handling of their functionality on to the camera and control system, respectively. UDNPawn.ucclass UDNPawn extends UTPawn; /* BecomeViewTarget Called by Camera when this actor becomes its ViewTarget */ simulated event BecomeViewTarget( PlayerController PC ) { local UDNPlayerController UDNPC; UDNPC = UDNPlayerController(PC); //Pawn is controlled by a UDNPlayerController and has a UDNPlayerCamera if(UDNPC != none && UDNPlayerCamera(UDNPC.PlayerCamera) != none) { //allow custom camera to control mesh visibility, etc. UDNPlayerCamera(UDNPC.PlayerCamera).BecomeViewTarget(UDNPC); } else { Super.BecomeViewTarget(PC); } } /** * Calculate camera view point, when viewing this pawn. * * @param fDeltaTime delta time seconds since last update * @param out_CamLoc Camera Location * @param out_CamRot Camera Rotation * @param out_FOV Field of View * * @return true if Pawn should provide the camera point of view. */ simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { //return false to allow custom camera to control its location and rotation return false; } /** * returns base Aim Rotation without any adjustment (no aim error, no autolock, no adhesion.. just clean initial aim rotation!) * * @return base Aim rotation. */ simulated singular event Rotator GetBaseAimRotation() { local vector POVLoc; local rotator POVRot; local UDNPlayerController PC; PC = UDNPlayerController(Controller); //Pawn is controlled by a UDNPlayerController and has a UDNPlayerCamera if(PC != none && PC.ControlModule != none) { //allow custom camera to control aim rotation return PC.ControlModule.GetBaseAimRotation(); } else { if( Controller != None && !InFreeCam() ) { Controller.GetPlayerViewPoint(POVLoc, POVRot); return POVRot; } else { POVRot = Rotation; if( POVRot.Pitch == 0 ) { POVRot.Pitch = RemoteViewPitch << 8; } return POVRot; } } } defaultproperties { }
GameInfo Class
The new gametype class is a basic extension of the UTDeathMatch class which sets the new HUD, Pawn, and PlayerController classes to use. It also sets bUseClassicHUD to True so that the HUD class specified here will be used instead of the UTGFxHUDWrapper, which is hardcoded to be used unless this boolean is set. UDNGame.ucclass UDNGame extends UTDeathMatch; defaultproperties { DefaultPawnClass=class'UDNExamples.UDNPawn' PlayerControllerClass=class'UDNExamples.UDNPlayerController' MapPrefixes[0]="UDN" }
Example Camera Module
As an example of using the new camera framework, a Top-Down camera will be set up. Making a new camera module is mainly a matter of implementing the functions defined in the base camera module class. Much of this will look familiar if you have gone through the CalcCamera() examples above. UDNCameraModule_TopDown.ucclass UDNCameraModule_TopDown extends UDNCameraModule; var float CamAltitude; //actual camera height offset from player var float DesiredCamAltitude; //new height offset to move camera to var float MaxCamAltitude; //maximum offset from player camera can be var float MinCamAltitude; //minimum offset from player camera can be var float CamZoomIncrement; //how many units to zoom with each click of mousewheel //Calculate new camera location and rotation function UpdateCamera(Pawn P, UDNPlayerCamera CameraActor, float DeltaTime, out TViewTarget OutVT) { //interpolate to new camera offest if not there if(CamAltitude != DesiredCamAltitude) { CamAltitude += (DesiredCamAltitude - CamAltitude) * DeltaTime * 3; } //align camera to player with height (Z) offset OutVT.POV.Location = OutVT.Target.Location; OutVT.POV.Location.Z += CamAltitude; //set camera rotation - face down OutVT.POV.Rotation.Pitch = -16384; OutVT.POV.Rotation.Yaw = 0; OutVT.POV.Rotation.Roll = 0; } //initialize new view target simulated function BecomeViewTarget( UDNPlayerController PC ) { if (LocalPlayer(PC.Player) != None) { //Set player mesh visible PC.SetBehindView(true); UDNPawn(PC.Pawn).SetMeshVisibility(PC.bBehindView); PC.bNoCrosshair = true; } } function ZoomIn() { //decrease camera height DesiredCamAltitude -= CamZoomIncrement; //lock camera height to limits DesiredCamAltitude = FMin(MaxCamAltitude, FMax(MinCamAltitude, DesiredCamAltitude)); } function ZoomOut() { //increase camera height DesiredCamAltitude += CamZoomIncrement; //lock camera height to limits DesiredCamAltitude = FMin(MaxCamAltitude, FMax(MinCamAltitude, DesiredCamAltitude)); } defaultproperties { CamAltitude=384.0 DesiredCamAltitude=384.0 MaxCamAltitude=1024.0 MinCamAltitude=160.0 CamZoomIncrement=96.0 }
Example Control Module
UDNControlModule_TopDown.ucclass UDNControlModule_TopDown extends UDNControlModule; //Calculate Pawn aim rotation simulated singular function Rotator GetBaseAimRotation() { local rotator POVRot; //aim where Pawn is facing - lock pitch POVRot = Controller.Pawn.Rotation; POVRot.Pitch = 0; return POVRot; } //Handle custom player movement function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot) { if( Controller.Pawn == None ) { return; } if (Controller.Role == ROLE_Authority) { // Update ViewPitch for remote clients Controller.Pawn.SetRemoteViewPitch( Controller.Rotation.Pitch ); } Controller.Pawn.Acceleration = NewAccel; Controller.CheckJumpOrDuck(); } //Calculate controller rotation function UpdateRotation(float DeltaTime) { local Rotator DeltaRot, NewRotation, ViewRotation; ViewRotation = Controller.Rotation; //rotate pawn to face cursor if (Controller.Pawn!=none) Controller.Pawn.SetDesiredRotation(ViewRotation); DeltaRot.Yaw = Controller.PlayerInput.aTurn; DeltaRot.Pitch = 0; Controller.ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot ); Controller.SetRotation(ViewRotation); NewRotation = ViewRotation; NewRotation.Roll = Controller.Rotation.Roll; if ( Controller.Pawn != None ) Controller.Pawn.FaceRotation(NewRotation, DeltaTime); } defaultproperties { }
Config Files
All of the files below should be located in the in the UDKgame/Config directory. Since some may be new additions, you will need to create those. Others can simply be modified to include the new configuration settings.. The DefaultCamera.ini file should be populated with the values for the various config variables found in the new camera classes. For this example, this consists of setting a default camera module class only. DefaultCamera.ini[UDNExamples.UDNPlayerCamera] DefaultCameraClass=UDNExamples.UDNCameraModule_TopDown
... [Engine.GameInfo] DefaultGame=UDNExamples.UDNGame DefaultServerGame=UDNExamples.UDNGame ... [UDNExamples.UDNPlayerController] DefaultControlModuleClass=UDNExamples.UDNControlModule_TopDown