Announcement

Collapse
No announcement yet.

[Tutorial] Third Person Game with GOW camera

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

    [Tutorial] Third Person Game with GOW camera

    MAIN TUTORIAL

    Hey there, I thought I'd post a tutorial on creating a third person game, the scripting involved and such. I know I would've liked something like this when I started scripting so hopefully it'll be useful to you! Please feel free to comment/critique/tear this apart below.

    So first off, this tutorial is assuming that you're a beginner who wants to create a third person game independent of UT with your own custom scripts, so I'll briefly go over a little bit of everything: setting up a new game, scripting, and other stuff like that. If you already know something, just skip over it.

    Setting up a new game:
    1. Create a folder "YourGame" (or whatever you'd like to call your game) inside ..[UDK-yyyy-mm]/development/src (yyyy-mm is just the date of the release you have).
    2. Inside of that, create a folder called "Classes."
    3. Inside of Classes, create four .uc files: YourGameInfo.uc, YourGamePawn.uc, YourGameCamera.uc, and YourGamePlayerController.uc.

    If you don't fancy these names, they're just to help you remember what they do and you can change them to whatever you like, it's the stuff inside that counts.

    Scripting:

    YourGameInfo.uc is the script that basically tells the UDK the basics about your game: what Player Controller to use, what pawn to use etc. Open up YourGameInfo.uc and insert the following code:
    Code:
    class YourGameInfo extends GameInfo; //This line tells UDK that you want to inherit all of the functionality of GameInfo.uc, and add your own. The name after "class" must match the file name.
    DefaultProperties //Self explanatory
    {
    bDelayedStart=false
    PlayerControllerClass = class 'YourGame.YourGamePlayerController' //Setting the Player Controller to your custom script
    DefaultPawnClass = class 'YourGame.YourGamePawn' //Setting the Pawn to your custom script
    }
    That's it for the Game Info script. Next we'll create the pawn. Unfortunately, this tutorial isn't entirely free of UT assets, as we'll be using a character mesh and animset from UT for lack of anything else. You can easily replace these with your own, though, if you get around to creating your own character and animations. The pawn is basically your character. It sets what your character looks like, how it collides with objects, how it's lit, and how it animates.

    Go ahead and paste the following code into YourGamePawn.uc
    Code:
    class YourGamePawn extends GamePawn; //Again, naming conventions apply here. Your script is extending the UDK script
    
    DefaultProperties
    {
            Components.Remove(Sprite)
    //Setting up the light environment
            Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment
                    ModShadowFadeoutTime=0.25
                    MinTimeBetweenFullUpdates=0.2
                    AmbientGlow=(R=.01,G=.01,B=.01,A=1)
                    AmbientShadowColor=(R=0.15,G=0.15,B=0.15)
                    LightShadowMode=LightShadow_ModulateBetter
      		        ShadowFilterQuality=SFQ_High
                    bSynthesizeSHLight=TRUE
            End Object
            Components.Add(MyLightEnvironment)
    //Setting up the mesh and animset components
    
        Begin Object Class=SkeletalMeshComponent Name=InitialSkeletalMesh
                    CastShadow=true
                    bCastDynamicShadow=true
                    bOwnerNoSee=false
                    LightEnvironment=MyLightEnvironment;
            BlockRigidBody=true;
            CollideActors=true;
            BlockZeroExtent=true;
    //What to change if you'd like to use your own meshes and animations
                    PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
                    AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_AimOffset'
                    AnimSets(1)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
                    AnimTreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
                    SkeletalMesh=SkeletalMesh'CH_LIAM_Cathode.Mesh.SK_CH_LIAM_Cathode'
            End Object
    //Setting up a proper collision cylinder
            Mesh=InitialSkeletalMesh;
            Components.Add(InitialSkeletalMesh); 
    		CollisionType=COLLIDE_BlockAll
    		Begin Object Name=CollisionCylinder
    		CollisionRadius=+0023.000000
    		CollisionHeight=+0050.000000
    		End Object
    		CylinderComponent=CollisionCylinder
    }
    
    //This lets the pawn tell the PlayerController what Camera Style to set the camera in initially (more on this later).
    simulated function name GetDefaultCameraMode(PlayerController RequestedBy)
    {
    	return 'ThirdPerson';
    }
    Most of these various values are pretty self explanatory, and you can either Google them, post here, or fiddle about with them if you can't figure out what they do.

    Now we'll continue to the custom Player Controller. (Getting into the tasty stuff!) I've commented the code below to provide an explanation of everything that's going on.

    Code:
    class YourGamePlayerController extends GamePlayerController;
    
    DefaultProperties
    {
    	CameraClass = class 'YourGameCamera' //Telling the player controller to use your custom camera script
    	DefaultFOV=90.f //Telling the player controller what the default field of view (FOV) should be
    }
    
    simulated event PostBeginPlay() //This event is triggered when play begins
    {
    	super.PostBeginPlay();
    	`Log("I am alive!"); //This sends the message "I am alive!" to thelog (to see the log, you need to run UDK with the -log switch)
    }
    //Functions for zooming in and out
    exec function NextWeapon() /*The "exec" command tells UDK to ignore what the defined function of NextWeapon is, and use our function declaration here.
    We'll go over how to change the function of keys later (if, for instance, you didn't want you use the scroll wheel, but page up and down for zooming instead.)*/
    {
    if (PlayerCamera.FreeCamDistance < 512) //Checks that the the value FreeCamDistance, which tells the camera how far to offset from the view target, isn't further than we want the camera to go. Change this to your liking.
    	{
    		`Log("MouseScrollDown"); //Another log message to tell us what's happening in the code
    		PlayerCamera.FreeCamDistance += 64*(PlayerCamera.FreeCamDistance/256); /*This portion increases the camera distance.
    By taking a base zoom increment (64) and multiplying it by the current distance (d) over 256, we decrease the zoom increment for when the camera is close,
    (d < 256), and increase it for when it's far away (d > 256).
    Just a little feature to make the zoom feel better. You can tweak the values or take out the scaling altogether and just use the base zoom increment if you like */
    	}
    }
    exec function PrevWeapon()
    {
    	if (PlayerCamera.FreeCamDistance > 64) //Checking if the distance is at our minimum distance
    	{
    		`Log("MouseScrollUp");
    		PlayerCamera.FreeCamDistance -= 64*(PlayerCamera.FreeCamDistance/256); //Once again scaling the zoom for distance
    	}
    }
    Now that we have the Player Controller worked out, we can move on to what most people are here for: the camera.

    This camera script incorporates zoom interpolation (smoothing) as well as a third person orbiting viewpoint. I'll lay this section out in three parts (each section should follow right after each other in the YouGameCamera.uc script.)

    First, we need to initialize the class instance and declare our variables:
    Code:
    class YourGameCamera extends Camera;
    
    // initializing static variables
    var float Dist;
    
    DefaultProperties
    {
    	FreeCamDistance = 256.f //
    }
    
    
    function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
    {
    //Declaring local variables
    local vector            Loc, Pos, HitLocation, HitNormal;
    local rotator           Rot;
    local Actor                     HitActor;
    local CameraActor       CamActor;
    local bool                      bDoNotApplyModifiers;
    local TPOV                      OrigPOV;
    A couple of things here. First of all, I've declared a variable outside of the function here in order to keep it static so that it doesn't re initialize each program loop. This just means my value will only change when I specifically tell it to. This sort of variable needs to be declared with the syntax, var variable_type variable_name; Second, I've set my FreeCamDistance to a default value so it doesn't start at some random value it grabbed out of memory.

    After this, we'll set up our view target and various settings to let our pawn override the camera style if need be.
    Code:
    // store previous POV, in case we need it later
    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) )
    {
    // don't apply modifiers when using these debug camera modes. 
    bDoNotApplyModifiers = TRUE;
    This is just pretty much taken from the camera.uc script, so there are a couple of things in there that are probably a bit unnecessary for what we're doing, but I've left them in there anyway.

    Next, we'll implement our actual camera styles. We're using a switch-case method here. Basically, the compiler enters the code where it finds a match to the CameraStyle, and exits if it hits a "break." Remember, our default state is ThirdPerson.

    Code:
    switch(CameraStyle)
    {
    case 'Fixed' : // No update, keeps previous view
    OutVT.POV = OrigPOV;
    break;
    
    case 'ThirdPerson' : //Enters here as long as CameraStyle is still set to ThirdPerson
    case 'FreeCam' :
    
    Loc = OutVT.Target.Location; // Setting the camera location and rotation to the viewtarget's
    Rot = OutVT.Target.Rotation;
    
    if (CameraStyle == 'ThirdPerson')
    {
    	Rot = PCOwner.Rotation; //setting the rotation of the camera to the rotation of the pawn
    }
    
    //OutVT.Target.GetActorEyesViewPoint(Loc, Rot);
    
    if(CameraStyle == 'FreeCam')
    {
    Rot = PCOwner.Rotation;
    }
    
    Loc += FreeCamOffset >> Rot;
    //Linear interpolation algorithm. This is the "smoothing," so the camera doesn't jump between zoom levels
    if (Dist != FreeCamDistance)
    {
    	Dist = Lerp(Dist,FreeCamDistance,0.15); //Increment Dist towards FreeCamDistance, which is where you want your camera to be. Increments a percentage of the distance between them according to the third term, in this case, 0.15 or 15%
    }
    
    Pos = Loc - Vector(Rot) * Dist; /*Instead of using FreeCamDistance here, which would cause the camera to jump by the entire increment, we use Dist, which increments in small steps to the desired value of FreeCamDistance using the Lerp function above*/
    // @fixme, respect BlockingVolume.bBlockCamera=false
    
    //This determines if the camera will pass through a mesh by tracing a path to the view target.
    HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12));
    //This is where the location and rotation of the camera are actually set
    OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation;
    OutVT.POV.Rotation = Rot;
    
    break; //This is where our code leaves the switch-case statement, preventing it from executing the commands intended for the FirstPerson case.
    
    case 'FirstPerson' : // Simple first person, view through viewtarget's 'eyes'
    default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    break;
    
    }
    }
    }
    
    if( !bDoNotApplyModifiers )
    {
    // Apply camera modifiers at the end (view shakes for example)
    
    ApplyCameraModifiers(DeltaTime, OutVT.POV);
    }
    //`log( WorldInfo.TimeSeconds  @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV );
    }
    Now that our scripting is finished, all that's left is to tell UDK to use our custom game type.

    Note: Please back up your config files before editing them. You'll probably be sorry if you don't.

    You'll need to go in to UDKGame\config and edit DefaultEngine.ini, and DefaultGameUDK.ini (make sure to turn of read-only on these files. In DefaultEngine.ini you'll need to edit:
    Code:
    Lines 6, 7 and 8,
    Map=UTFrontEnd.udk
    LocalMap=UTFrontEnd.udk
    TransitionMap=EnvyEntry.udk
    Change the value of the first two entries to the map you'd like to start on,
    and if you like, change the third entry to your own custom loading screen map.
    
    Add: +EditPackages=YourGame under [UnrealEd.EditorEngine] on line 15
    In DefaultGameUDK.ini you'll need to edit:
    Code:
    Lines 5, 6 and 7,
    DefaultGame=UTGame.UTDeathmatch
    DefaultServerGame=UTGame.UTDeathmatch
    PlayerControllerClassName=UTGame.UTPlayerController
    Change the first two entries to YourGame.YourGameInfo, and the third entry to YourGame.YourGamePlayerController.
    Now for a couple of notes: First off, please note that this ini editing is quite basic and does not change any behavior related to how UDK builds packages, or includes packages when you "make" the game from the front end. For more advanced ini editing please check out tutorials such as The Ball for more information. Second, for your custom maps and content you'll need to create a folder "YourGame" under UDKGame\Content.

    Now you're almost all finished. The last step is to open the UDK Launcher and click "make." Voila, your game should be playable in editor and from the launcher now!

    SHOULDER CAMERA TUTORIAL EXTENSION

    Warning: Over-the-shoulder camera section may contain mathematics

    Alright, to get an over-the-shoulder camera working, we need to make a few changes to the above scripts. YourGameInfo and YourGamePawn both stay the same, so we'll be concentrating the changes in the player controller and especially the camera script.

    Step one: Custom keybinding

    First, we need to bind a key to switch camera views. For this, I use the left shift key. I have it activate the camera on a press, return to third person on release. Go into UDKGame\Config, and add the following to UDKInput.ini:
    Code:
    Line 29 add:
    Bindings=(Name="LeftShift",Command="ShoulderCam | OnRelease ReturnCam")
    This tells the UDK that we want left shift to call a command (which we'll define in our player controller script) called ShoulderCam when the button is pressed, and ReturnCam when it is released.

    Step two: PlayerController

    We're going to make the following edits to YourGamePlayerController.uc:

    First we need to declare an additional variable. This should go directly under the class declaration.
    Code:
    var float PreDist;
    This variable will store our previous camera distance so that when we switch back to the normal camera, we'll be at our original setting.

    The next lines of code should be tacked directly on the end of the player controller script:

    Code:
    exec function ShoulderCam() // Declaring our ShoulderCam function that we bound to
    {
    	`Log("Shoulder Camera"); // Yet another log...
    	PreDist = PlayerCamera.FreeCamDistance; //Storing our previous camera distance...
    	YourGameCamera(PlayerCamera).CameraStyle = 'ShoulderCam'; //Type casting our camera script to access the variable CameraStyle
    }
    
    exec function ReturnCam() //This is called on release of left shift
    {
    	`Log("Main Camera");
    	PlayerCamera.FreeCamDistance = PreDist; // Restoring the previous camera distance
    	YourGameCamera(PlayerCamera).CameraStyle = 'ThirdPerson'; // Restoring the previous camera style
    }
    That's all we need in YourGamePlayerController. Now we move on to the fun part: Camera implementation.

    Step three: Camera Scripting

    There are numerous small edits to make in YourGameCamera, so I'll post a completed script at the end.

    Declaring variables

    We're going to need 6 new static variables in our camera script. These should be declared as follows beneath our declaration of Dist

    Code:
    var float TargetFOV; //Lerp target for field of view
    var float Z; //Current Z axis offset
    var float TargetZ; //Lerp target for Z offset 
    var float Offset; //Current amount of XY offset
    var float TargetOffset; //Lerp target for XY offset
    var float pival; // pi
    Under defaultproperties make the following addition:

    Code:
    pival = 3.14159; //The aprox. value of pi
    Now we move down to our switch/case structure. We're going to need to add another case for our shoulder camera. Add the following under "case 'FreeCam' :"

    Code:
    case 'ShoulderCam' : //Our shoulder camera case
    Now, with the addition of those new variables, we're going to have to declare what they should be for each of our cameras. Modify the if statement "if (CameraStyle == 'ThirdPerson')" to read:

    Code:
    if (CameraStyle == 'ThirdPerson')
    {
    	Rot = PCOwner.Rotation; //setting the rotation of the camera to the rotation of the pawn
    	TargetZ = 0; //We don't want any z axis offset
    	TargetFOV = 90; //We want to have our field of view set to the default 90 degrees
    	TargetOffset = 0; // No xy offset either
    }
    No we add an if statement for our new camera style under the prior if statement:

    Code:
    if (CameraStyle == 'ShoulderCam')
    {
    	Rot = PCOwner.Rotation; //We still want to use the rotation of the character as our camera rotation
    	FreeCamDistance = 64; //We'll go in for a close up
    	TargetFOV = 60.f; //And we'll have a nice zoom effect for aiming
    	TargetZ = 32; //We'll pop the camera up above the head...
    	TargetOffset = 32; //And pop it out over the shoulder
    }
    Now we need to add in the effect of the z offset on our camera location. Add the following line of code after "Loc += FreeCamOffset >> Rot;"

    Code:
    Loc.Z += Z; // Setting the Z coordinate offset for shoulder view
    Now we'll make sure nothing "jumps," and everything is silky smooth. We'll add three more lerps--one for each of our variables that get changed with the camera style. Under the lines:
    Code:
    if (Dist != FreeCamDistance)
    {
    	Dist = Lerp(Dist,FreeCamDistance,0.15);
    }
    Enter the additional lines:

    Code:
    if (Z != TargetZ) //Lerping z offset
    {
    	Z = Lerp(Z,TargetZ,0.1);
    }
    if (DefaultFOV != TargetFOV) //Lerping FOV
    {
    	DefaultFOV = Lerp(DefaultFOV,TargetFOV,0.1);
    }
    if (Offset != TargetOffset) //Lerping xy offset
    {
    	Offset = Lerp(Offset,TargetOffset,0.1);
    }
    Now, this next part is where our math comes in. We can't just tell the UDK to offset our camera on the x and y axes, since then, when our character turned around, our offsets would still be in the same direction, and it would be the exact opposite of what we want for that rotation.

    The problem lies in the fact that we're working in world coordinates, so any offset we make will be in global, rather than local, character coordinates.

    We solve this by mapping our character offset from character coordinates to world coordinates using a little trigonometry.

    Add the following two lines of code under "Pos = Loc - Vector(Rot) * Dist;" (this should be directly under our lerp code)

    Code:
    Pos.X += Offset*sin(-Rot.Yaw*pival*2/65536);
    Pos.Y += Offset*cos(Rot.Yaw*pival*2/65536);
    Those two lines tell the UDK to offset the camera in a direction off of the pawn rather than in a global direction. The numbers after Rot.Yaw convert from UnrealUnits to radians. If you're familiar with trigonometry and vectors, you probably won't find this too complicated. If you're not familiar with that stuff, don't worry about it, just use it as is and learn it later.

    That takes care of all the changes we need in the YourGameCamera.uc Here's the completed script to give you an idea of what it looks like all put together:

    Code:
    class YourGameCamera extends Camera;
    
    // initializing static variables
    var float Dist;
    var float TargetFOV;
    var float TargetZ;
    var float Z;
    var float TargetOffset;
    var float Offset;
    var float pival;
    
    DefaultProperties
    {
    	FreeCamDistance = 256.f
    	pival = 3.14159;
    }
    
    
    function UpdateViewTarget(out TViewTarget OutVT, float DeltaTime)
    {
    //Declaring local variables
    local vector            Loc, Pos, HitLocation, HitNormal;
    local rotator           Rot;
    local Actor                     HitActor;
    local CameraActor       CamActor;
    local bool                      bDoNotApplyModifiers;
    local TPOV                      OrigPOV;
    
    // store previous POV, in case we need it later
    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) )
    {
    // don't apply modifiers when using these debug camera modes. 
    bDoNotApplyModifiers = TRUE;
    
    switch(CameraStyle)
    {
    case 'Fixed' : // No update, keeps previous view
    OutVT.POV = OrigPOV;
    break;
    
    case 'ThirdPerson' : //Enters here as long as CameraStyle is still set to ThirdPerson
    case 'FreeCam' :
    case 'ShoulderCam' : // Over the shoulder view
    
    Loc = OutVT.Target.Location; // Setting the camera location and rotation to the viewtarget's
    Rot = OutVT.Target.Rotation;
    
    if (CameraStyle == 'ThirdPerson')
    {
    	Rot = PCOwner.Rotation; //setting the rotation of the camera to the rotation of the pawn
    	TargetZ = 0;
    	TargetFOV = 90;
    	TargetOffset = 0;
    }
    
    if (CameraStyle == 'ShoulderCam')
    {
    	Rot = PCOwner.Rotation;
    	FreeCamDistance = 64;
    	TargetFOV = 60.f;
    	TargetZ = 32;
    	TargetOffset = 32;
    }
    
    //OutVT.Target.GetActorEyesViewPoint(Loc, Rot);
    
    if(CameraStyle == 'FreeCam')
    {
    Rot = PCOwner.Rotation;
    }
    
    Loc += FreeCamOffset >> Rot;
    Loc.Z += Z; // Setting the Z coordinate offset for shoulder view
    
    //Linear interpolation algorithm. This is the "smoothing," so the camera doesn't jump between zoom levels
    if (Dist != FreeCamDistance)
    {
    	Dist = Lerp(Dist,FreeCamDistance,0.15); //Increment Dist towards FreeCamDistance, which is where you want your camera to be. Increments a percentage of the distance between them according to the third term, in this case, 0.15 or 15%
    }
    if (Z != TargetZ)
    {
    	Z = Lerp(Z,TargetZ,0.1);
    }
    if (DefaultFOV != TargetFOV)
    {
    	DefaultFOV = Lerp(DefaultFOV,TargetFOV,0.1);
    }
    if (Offset != TargetOffset)
    {
    	Offset = Lerp(Offset,TargetOffset,0.1);
    }
    
    Pos = Loc - Vector(Rot) * Dist; /*Instead of using FreeCamDistance here, which would cause the camera to jump by the entire increment, we use Dist, which increments in small steps to the desired value of FreeCamDistance using the Lerp function above*/
    // Setting the XY camera offset for shoulder view
    Pos.X += Offset*sin(-Rot.Yaw*pival*2/65536);
    Pos.Y += Offset*cos(Rot.Yaw*pival*2/65536);
    // @fixme, respect BlockingVolume.bBlockCamera=false
    
    //This determines if the camera will pass through a mesh by tracing a path to the view target.
    HitActor = Trace(HitLocation, HitNormal, Pos, Loc, FALSE, vect(12,12,12));
    //This is where the location and rotation of the camera are actually set
    OutVT.POV.Location = (HitActor == None) ? Pos : HitLocation;
    OutVT.POV.Rotation = Rot;
    
    break; //This is where our code leaves the switch-case statement, preventing it from executing the commands intended for the FirstPerson case.
    
    case 'FirstPerson' : // Simple first person, view through viewtarget's 'eyes'
    default : OutVT.Target.GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation);
    break;
    
    }
    }
    }
    
    if( !bDoNotApplyModifiers )
    {
    // Apply camera modifiers at the end (view shakes for example)
    
    ApplyCameraModifiers(DeltaTime, OutVT.POV);
    }
    //`log( WorldInfo.TimeSeconds  @ GetFuncName() @ OutVT.Target @ OutVT.POV.Location @ OutVT.POV.Rotation @ OutVT.POV.FOV );
    }
    Now you're finished. Just compile your script from the front end or your favorite method, and voila, (sort of) instant shoulder cam!

    Good luck, cheers, and thanks!

    JT

    #2
    Thanks for taking the time to do this. I would like to ask you a few questions and pick your brain if I may...

    Firstly, I followed your tutorial and when I play a level it defaults to a free roaming first person camera. Is this right?

    I gather from your script that there are two different cameras but I can't see how you can switch them, so I'm not sure.

    I'll have a few more questions, but these were the most important ones.

    Thanks again

    Comment


      #3
      This would be awesome!!!!

      If it worked...



      I came back and copied these scripts TO THE LETTER and they still failed to compile... Then I copied and pasted and STILL got failed compile.

      Comment


        #4
        Hey guys, thanks for bearing with me, this is my first tutorial. There was a little confusion with switching this code to the April release, and just some miscellaneous coding and wording issues when I was writing it in tutorial form. I've fixed all the bugs and retested every line of code, along with the ini edits so the tutorial should be a breeze now. Thanks for all the feedback!

        [edit] just for reference, the stuff I changed is:

        Error in naming pawn

        Added bDelayedStart=false in gameinfo script (very important!!)

        Fixed syntax errors in playercontroller script

        Corrected defaultgame.ini to defaultgameudk.ini (an april release thing)

        Added +EditPackages=YourGame to defaultengine.ini (also very important!)

        Added note about content folder.

        Do go through the tutorial again just to make sure I haven't missed any changes here.

        Thanks again, and please post any questions you have!

        Comment


          #5
          very nice tutorial
          big thanks!

          Comment


            #6
            this is awesome! I think I may get some decent mileage out of this one

            Comment


              #7
              I'll give it a whirl again. Thanks for the update.

              EDIT: Awesome, compiled without so much as a warning. I am about to go check it out right now.

              EDIT 2: Very nice. And well-commented too. Alas, I finally understand how to use an external camera class. Thank a billion.

              Comment


                #8
                Hey, thanks a lot guys, I'm glad this is getting some use. I've uploaded a video on youtube of the script in action, along with an additional toggleable over-the-shoulder cam. If you'd like to see the scripting for that, too, just let me know.

                Here's the vid: http://www.youtube.com/watch?v=lwOOQgtSxak

                Comment


                  #9
                  hey, I'm experiencing some errors (49 of them) all being upset about the engine's inability to find superclasses all beginning with UT, but I can't find any way to convert the references to UDK, can you help? there's probably an obvious reference in there, but I'm not a coder, and I can't seem to find it.

                  EDIT; fixed the inability to find UT stuff by going into the default engine.ini and changing +EditPackages=UTGameContente to +EditPackages=UDKGameContent
                  but I get a warning that it can't find C:\UDK\UDK-2010-04\Binaries\Win32\..\..\Developement\Src\UDKGameCo ntent\Classes\*.uc
                  Any suggestions?

                  Comment


                    #10
                    This tutorial was written before the April Release

                    Comment


                      #11
                      No, actually, I'm using the April release right now. I was using it when I wrote the tutorial a few days ago. Can you post an error sample?

                      Thanks!

                      Comment


                        #12
                        What is the name of your game folder under UDk\udk-2010-04\development\src? Are you sure that the name of your folder matches the references in your script? Also, is there an unintended space in "UDKGameCo ntent?" It's sounds like you made a typo somewhere in your script or ini files.

                        Comment


                          #13
                          @Psilocybe: If you could post the script for the Over-The-Shoulder camera, that would be great.

                          This zoom-able cam is cool and works well for my menu (I have a map that you can run around and interact with different elements rather than a traditional 2d-type menu. Kind of like Conker's Bad Fur Day from N64 where each door takes you to a different option/game save/etc and opens a new UIScene), but for the actual gameplay I was hoping for a slightly zoomed-out over-the-shoulder cam.

                          Of course, there's no rush on that and I may figure it out on my own before you get to it, but it may be helpful to others as well.

                          Comment


                            #14
                            Ok, I've updated the tutorial to include the shoulder camera. I hope it's about the right depth for everyone. It's now a bit long, so let me know if you have or find any problems with it.

                            Thanks!

                            Comment


                              #15
                              Very very useful tut.
                              Thank you very much.

                              Comment

                              Working...
                              X