Announcement

Collapse
No announcement yet.

Make Third Person Custom Player Cameras work with UTGame / UTPlayerController

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Make Third Person Custom Player Cameras work with UTGame / UTPlayerController

    Dear Community,

    In this tutorial I am showing you how you can get your custom cameras to work with UTGame.

    I also provide you with the entire basic custom camera code to

    1. set a focal actor for your camera to follow
    2. determine an offset from the focal actor's location
    3. set further custom variables for pitch, horizontal distance, and vertical distance from focal point

    These are variables that you can then modify in your player controller class to make your 3rd person camera fully adjustable during game time.


    ~~~

    Proof of Camera-Class Camera working with UT Game in Actual Multiplayer Game



    ~~~

    BackGround Info

    If you are not familiar, UTPlayerController gets rid of any playercameras that spawn, see the code in blue

    Code:
    simulated event GetPlayerViewPoint( out vector POVLocation, out Rotator POVRotation )
    {
    	local float DeltaTime;
    	local UTPawn P;
    
    	P = IsLocalPlayerController() ? UTPawn(CalcViewActor) : None;
    	
    	if (PlayerCamera == None
    		&& LastCameraTimeStamp == WorldInfo.TimeSeconds
    		&& CalcViewActor == ViewTarget
    		&& CalcViewActor != None
    		&& CalcViewActor.Location == CalcViewActorLocation
    		&& CalcViewActor.Rotation == CalcViewActorRotation
    		)
    	{
    		if ( (P == None) || ((P.EyeHeight == CalcEyeHeight) && (P.WalkBob == CalcWalkBob)) )
    		{
    			// use cached result
    			POVLocation = CalcViewLocation;
    			POVRotation = CalcViewRotation;
    			return;
    		}
    	}
    	
    	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
    	{
    		/*
    		if ( PlayerCamera != None )
    		{
    			PlayerCamera.Destroy();
    			PlayerCamera = None;
    		}
    		*/
    		if ( 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;
    			}
    		}
    		else
    		{
    			CalcCamera( DeltaTime, POVLocation, POVRotation, FOVAngle );
    			return;
    		}
    	}
    
    	// 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;
    	}
    }
    and UTGame forces the use of UpdateRotation in UTPlayerController when pawns are present.

    The Result:

    Getting custom cameras to work with UTGame is extremely difficulty!

    ~~~

    I discovered I need to use UTGame for multiplayer to work easily for me, but was in a jam because I wanted to use my custom camera.


    So through dint of problem solving and perserverance I can now present to you a way to get custom cameras to work in games extending UTGame

    ~~~

    Player Controller Class

    Code:
    var vector ThirdPersonCamOffset;
    var float CamTurnSpeed;
    var YourCameraBase CameraBase;
    
    simulated event postbeginplay(){
        super.postbeginplay();
    
            //================
    	//Camera!
    	
    	//GET CAMERA BASE
    	CameraBase = YourCamera(PlayerCamera).getCameraBase();
    	
    	//PC for Camera
    	CameraBase.setYourPC(Self);
    	
    	//actor for camera to follow
    	CameraBase.setfocalActor(Pawn);
    	
    	//===========================
    }
    
    function UpdateRotation( float DeltaTime )
    {
       local Rotator   DeltaRot, ViewRotation;
      
       ViewRotation = Rotation;
       
       if (Pawn!=none) 
       {
    		
    	Pawn.SetDesiredRotation(ViewRotation);
       }
      
       //=================================
    	
       
       // Calculate Delta to be applied on ViewRotation
       DeltaRot.Yaw   = PlayerInput.aTurn * CamTurnSpeed;
       DeltaRot.Pitch   = PlayerInput.aLookUp;
    
    	
    	//retrieves new rotation data from playerinput values
    	ProcessViewRotation( DeltaTime, ViewRotation, DeltaRot );
       
    	
    	SetRotation(ViewRotation);
    
    	//Makes sure to apply any view shake, yaaay
    	ViewShake( deltaTime );
    	
        
        
    	r = ViewRotation;
    	r.Roll = Rotation.Roll;
    
       
    	if (Pawn!=none)
    	{
    		
    	  Pawn.FaceRotation(r, deltatime);
    	}
    
    }   
    
    state PlayerWalking
    {
    	//nullified
    	
    }
    
    /* 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;
    
    	//use camera values
    	POVLocation = PlayerCamera.ViewTarget.POV.Location;
            POVRotation = PlayerCamera.ViewTarget.POV.Rotation;
            FOVAngle = PlayerCamera.ViewTarget.POV.FOV;
    	
    	//cache camera vars
    	CalcViewLocation 		= POVLocation;
    	CalcViewRotation 		= POVRotation;
    	
    	return;
    }
    
    defaultproperties
    {
         CameraClass = class'YourCamera'
         CamTurnSpeed = 1.4
    }
    ~~~

    Pawn Class

    Code:
    //no calc cam
    simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV )
    {
    	return false;
    	
    }
    ~~~

    Example of a custom Camera Class

    Code:
    class YourCamera extends GamePlayerCamera;
    
    simulated function YourCameraBase getCameraBase() {
    	//`log("getcamerabase did run"@Self.name);
    	return YourCameraBase(thirdpersoncam);
    }
    
    protected function GameCameraBase FindBestCameraType(Actor CameraTarget)
    {
    	return ThirdPersonCam; // could have other camera options
    }
     
    DefaultProperties
    {
        ThirdPersonCameraClass=class'YourCameraBase'
        ThirdPersonCamOffset=(x=-160, y=8, z=20)
    }
    ~~~

    Example CameraBaseClass

    note you must call setFocalActor before this class below will function properly

    I do so in postbeginplay of playercontroller code above

    Code:
    //=========================================================
    
    //Note this class is largely based on a Mougli tutorial
    
    //Thank you Mougli!
    
    //-Rama
    //=========================================================
    class VictoryBallCameraBase extends GameCameraBase;
    
    var YourController YourPC;
    
    //Must Be Set From External Class
    var actor focalActor;
    
    var Rotator CurrentCamOrientation;
    var Rotator DesiredCamOrientation;
    
    //set these offset from playercontroller
    //to adjust camera during gameplay
    //using exec key presses
    var float zOffset;
    var float pitchOffset;
    var float horizontalOffset;
    
    var rotator r;
    
    
    function setYourPC( YourController YourPCi) {
    	YourPC = YourPCi;
    }
    function setFocalActor(Actor a) {
    	focalActor = a;
    }
    
    function init(){
    	
    	`log("============ Yourcam Started =============");
    	`log("============ Yourcam Started =============");
    	`log("============ Yourcam Started =============");
    	`log("============ Yourcam Started =============");
    	
    }
    
    function restoreCam() {
    	horizontalOffset 	= 0;
    	zOffset 			= 0;
    	pitchOffset 		= 0;
    }
    
    function UpdateCamera(Pawn P, GamePlayerCamera CameraActor, float DeltaTime, out TViewTarget OutVT)
    
    {
        local float Radius, Height;
        local vector X, Y, Z;
    	
    	if (YourPC == none) return;
    	
        focalActor.GetAxes(DesiredCamOrientation,X,Y,Z); // We will be working with coordinates in pawn space, but rotated according to the Desired Rotation.
    	focalActor.GetBoundingCylinder(Radius, Height); //Get the pawn's height as a base for the Z offset.
    	
    	
    	//removing roll acquired during UTplayercontroller transition
    	DesiredCamOrientation.roll 	= 0;
    	DesiredCamOrientation.pitch += pitchOffset;
    
    		
    	//Location
    	OutVT.POV.Location = VInterpTo(OutVT.POV.Location, 
    		focalActor.Location + YourPC.ThirdPersonCamOffset.X * X 
    							+ YourPC.ThirdPersonCamOffset.Y * Y 
    							+ (Height + YourPC.ThirdPersonCamOffset.Z) * Z, 
    		DeltaTime, 
    		7
    	);
    		
    	OutVT.POV.Location.z += zOffset;
    		
    	r = DesiredCamOrientation;
    	r.roll = 0;
    	r.pitch = 0;
    	r.yaw += 16384;
    	OutVT.POV.Location += Vector(r) * horizontalOffset;
    		
    	//Rotation
    	if (DesiredCamOrientation != CurrentCamOrientation)
    	{
    		CurrentCamOrientation = RInterpTo(CurrentCamOrientation, DesiredCamOrientation, DeltaTime, 12);
    			
    	}
    	OutVT.POV.Rotation 	= CurrentCamOrientation;
    	
    	//removing roll acquired during UTplayercontroller transition
    	OutVT.POV.Rotation.roll = 0;
    	
    }
     
    function ProcessViewRotation( float DeltaTime, Actor ViewTarget, out Rotator out_ViewRotation, out Rotator out_DeltaRot )
    {
       
    	DesiredCamOrientation = out_ViewRotation + out_DeltaRot;
    	
    }
    ~~~

    Summary

    Now you can easily fully implement custom cameras, the entire basic code I am providing here, which you can add to by:

    Setting up exec functions in your playercontroller class to modify these yourcamerabase variables:

    Code:
    var float zOffset;
    var float pitchOffset;
    var float horizontalOffset;
    Do note that cameras can also have their own post process effects

    Check out engine.camera.uc to see all the cool options for cameras that you can now implement in your game that extends utGame!




    Rama
Working...
X