sega 500 building a vehicle jeff “ezeikeil” giles [email protected] jgiles

87
Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles [email protected]

Upload: clemence-parker

Post on 17-Jan-2016

218 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Sega 500

Building a Vehicle

Jeff “Ezeikeil” [email protected]://gamestudies.cdis.org/~jgiles

Page 2: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Today…

Was a result of my getting just a little too ambitious… We’re going to look at what it takes to get a simple vehicle into UT

From scratch!

Page 3: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

No small task

I’ve be wrestling with the idiosyncrasies of working with vehicles and the Karma physics for a while now and, as you about to see…it’s not light.

This is further complicated by the docs…which are as usual, M.I.A.

Page 4: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The docs we do have…

If you root through the UDN, there are lots of docs related to Karma there, however, none (that I can find) adequately explain exactly what specific UScript Karma functions to.

However, there is the complete Karma users manual.pdf for download…for working in C++.

Page 5: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The Examples we do have…

Also tent to be geared towards the editor and placing Karma objects in the world.

And one descriptions of the Bulldogs defaults and what playing with those values will do.

Nothing other than one example of a vehicle on the Wiki…which is essentially a modified Bulldog.

Page 6: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Keep in mind…

The sample code for today is a long way from what I would consider “complete”.

And it still has some issues, which we will deal with as we get to them.

But I feel that it’s a reasonable introduction to the steps required.

Page 7: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

That Being said…

What I’m hoping to demonstrate today is a start point to setting up a Karma vehicle in UT and hopefully solve a few issues you may encounter.

What we will have by the end of today is a function car with throttle, karma, and steering…built from a custom model.

Page 8: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Starting with…

A plan. First off, we need a few parts for the car.

The frame, or body. This is what the player will see.

The wheels. These have to separate from the model so we can make the do things… like rotate.

And collision parameters.

Page 9: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The model.

I whipped up the basic shape of a car in 3DS Max…and I mean…Basic.

Page 10: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

However,

There is some interesting ticks going on here.

Now, if you were to follow the Bulldog as an example, you’d see that they use static meshes for it. Which is fine.

But figuring out exactly where the wheels attach to the body can be a real pain.

Page 11: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The reason?

Well, Static meshes in UT don’t allow you to put bones in them to use as markers to attack to the object…Hence you have to do some significant planning to get the wheels to where you want them.

Page 12: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Not letting UT get in the way…

We’re not going to let that stop us from using bones to attach the wheels to the vehicle.

Bones

Page 13: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Essentially, we grow a brain

Now bare with me here…

Inside my mesh I place the bones where I want to attach the wheels, making sure that they are properly oriented.

Then I group them with the body of the car. This is why the get textured. Normally you would not see them.

Page 14: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Naming the bones

Also, make sure they have appropriate names.

This is how we will know where to attach the wheel…this is important.

BoneRF Right Front

BoneLF Left Front

BoneRR Right Rear

BoneLR Left Rear

Page 15: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And then…

Once grouped up, we export the mesh through actorX into a psk. NOT as an ASE.

Hang on? If you going to use karma, you Have to use static meshes!!! The UDN says so!

Page 16: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Well, true…

But this is us being clever and using some smoke and mirrors to get this done.

Only the collision object needs to be a static mesh…See where I’m going with this?

If not, you’ll see in a sec…

Page 17: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And the Wheels…

Simple model up a simple wheel for the car.

Make sure its at the world origin! Not where you would attach it to the car.

This is because we use the origin as the attach point.

Page 18: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Collision Hulls

Now using the modeling environment, we create separate collision volumes foe the wheels.

Simply create a volume around it with a name like MCDCX_Wheel.

Note: a cylinder is shown here for collisionbut I have since found that a sphere works best.

Page 19: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Collision Hulls

Then group and export the wheel as an ASE…not a PSK.

We need the collision on the wheels.

And now for the body…

Page 20: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Smoke and mirrors

Using the same technique, we create a collision volume for the car. I deliberately didn’t fit it too closely to the car.

This will result in a volume some thing like:

Page 21: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Smoke and mirrors

Where the yellow is the collision volume.

Page 22: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

A trick of the light

But you said it’s a PSK! No Collision! I call foul!

We are not done yet, I set this up in a very specific manner, if we look inside the car…

Page 23: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

A trick of the light

We actually have another object…a 16,16,16 cube…which IS a static mesh.

Collision volume Static mesh

Page 24: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The Magic…

We the group these objects together and export them (not the car! Just the collision hull and the cube) as an ASE?

Seeing the plan yet?

Page 25: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Slight of hand…

If not, here it is. We now have a static mesh which we will

use to calculate the collisions which will be the car itself.

And a mesh object which we will then bind to the static mesh (the car) through code.

Page 26: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Slight of hand…

Then we can attach the wheels to the car at the location of the bones in the mesh through a call to attachtobone().

And this makes creating the car super convenient.

Page 27: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And there is another bonus

If I wanted to, I could now ANIMATE the car mesh itself.

And it will do play that animation where ever the car (static mesh) goes.

Cool…Nes pas?

Page 28: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

So in code…

How do we hook this up?

Well the body simple needs to show up so: class Ebody extends Actor;

DefaultProperties{ Mesh=mesh'SimpleCar.car' DrawType=DT_Mesh}

Page 29: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Then in the actual car class…

We create a function to assemble the car. I do this in Prebeginplay of the Ecar class.

function PreBeginPlay(){ // build the car Carframe=spawn(class'EBody',self,,Location); Carframe.SetBase(self); Carframe.SetCollision(true,true,true); InitWheels();

Page 30: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

In these three lines….

We create the body and bind it to the collision of the Ecar.

This bind done through a call to set base. And because the EBody is inside the Ecar’s collision volume, it should never be lodged free!

Page 31: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Attaching the wheels…

Well, Prebeginplay calls InitWheels() which does all the attaching as setting up of the wheels.

Page 32: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

InitWheels

function InitWheels(){ CreateTire(LFTire,'BoneLF'); CreateTire(LRTire,'BoneLR'); CreateTire(RFTire,'BoneRF'); CreateTire(RRTire,'BoneRR');

//specific to front wheels LFTire.WheelJoint.bKSteeringLocked=false; RFTire.WheelJoint.bKSteeringLocked=false;}

Page 33: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

InitWheels

Now, there is a lot of common functionality going on between the 4 tires, so I further wrapped them up into a another function…CreateTire.

Do notice that we use an out operation to set the tire.

function CreateTire(out Etire tire, name attachbone)

Page 34: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

Now, in this function there is a lot going on…and I mean A LOT!

But the 1st thing to note, this is where we do the attach to bone thing…

BoneLoc=Carframe.GetBoneCoords(attachbone).origin;tire=spawn(class'Etire',self,,BoneLoc);tire.AttachToBone(CarFrame,attachbone);tire.SetBase(self);

Page 35: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

This will create and bind the tire to a specific bone in the body of the car (Ebody).

If you were to spawn it now…

Page 36: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

But it won’t do anything…Other than be ugly.

Page 37: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

And this is where it starts to get crazy…As we are about to hook up the Karma.

The next step is to access some of the Karma functionality to make sure the wheels line up properly.

Page 38: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

This is one of those build-in-native-and-not-documented functions.

KGetRigidBodyState accesses KRigidBodyState of the object (tire here) and returns a bunch of parameters…

tire.KGetRigidBodyState(ks);ks.Position.Z-=140; // ugh...magic number....bad...no twinkie!pos=KRBVecToVector(ks.Position);

Page 39: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KrigidBodyState

Is a struct that is critical to the functionality of the vehicle. I spent hours trying to figure out why my collision hulls would pull away from the wheels

struct KRigidBodyState{

var KRBVec Position;var Quat Quaternion;var KRBVec LinVel;var KRBVec AngVel;

};

Page 40: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KrigidBodyState

What would happen is these collision volumes (green) would fly away from the tire…really weird.

Like I said…Hours.

Page 41: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KrigidBodyState

Essentially we use the Karma components to a position back from the native code.

We then use it to position the collision volumes.

And the magic number is a necessary evil right now.

tire.KGetRigidBodyState(ks);ks.Position.Z-=140; // ugh...magic number....bad...no twinkie!pos=KRBVecToVector(ks.Position);

Page 42: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KrigidBodyState

This is what happens if I don’t use it…

Wheel

The Wheels collision

Page 43: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KrigidBodyState

Now I’m absolutely convinced that this is a result of my not properly using the KrigidBodyState to update the car as the Kcar actually passes around a KRigidBodyState as a parameter…I do not do so in the same manner.

But like I said…no docs, and the bulldog is huge!

Page 44: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

Ok, back to the tire… The other critical object to get this to work

is the kwheeljoint which is build into every class which is derived from KTire.

Thus we spawn one here.

tire.WheelJoint = spawn(class'KCarWheelJoint', self);

Page 45: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KCarWheelJoint

This is essentially how karma does it’s thing.

It is in fact the joint which connects to the wheel the body of the car.

Page 46: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

An then we need to set it’s parameters. Most if this is straight from bulldog. (other than the placement).

My changes are in italics…

Page 47: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

tire.WheelJoint.KPos1 = pos/50; // scale collision params of //wheel to car

tire.WheelJoint.KPriAxis1 = vect(0, 0, 1);tire.WheelJoint.KSecAxis1 = vect(0, 1, 0);tire.WheelJoint.KConstraintActor1 = self;tire.WheelJoint.KPos2 = vect(0, 0, 0);tire.WheelJoint.KPriAxis2 = vect(0, 0, 1);tire.WheelJoint.KSecAxis2 = vect(0, 1, 0);tire.WheelJoint.KConstraintActor2 = tire;tire.WheelJoint.SetPhysics(PHYS_Karma);

Joint axis

Page 48: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

Recall that pos is recalculated using the KGetRigidBodyState.position to more accurately position the collision hull.

The next bit, is that we specify what to actors the joint is linked to…the body and the wheel.

tire.WheelJoint.KPos1 = pos/50; // scale collision params of //wheel to car

tire.WheelJoint.KConstraintActor1 = self;tire.WheelJoint.KConstraintActor2 = tire;

Page 49: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

CreateTire

And the last thing I did, just so that I can see where the joints are, I spawn some xemitters at the same location, and bind them to the joins. This made debugging a bit easier.

spawn(class'TransTrail',,,tire.WheelJoint.location).setbase(tire.wheeljoint);

Page 50: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Back to PreBeginPlay…

Whiew…now that’s out of the way, we can finish off this function.

Right after the call to initwheels, we set some krama mass parameters for each object. This is just so Karma can calculate things like momentum.

native final function KSetMass( float mass );

Page 51: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KSetMass

Is actually an internal function, so we can’t ever see what gets set.

However, it has to be done or your physics will zero out…nothing will happen when you try to accelerate. KSetMass(ChassisMass); LFTire.KSetMass(TireMass); RFTire.KSetMass(TireMass); RRTire.KSetMass(TireMass); LRTire.KSetMass(TireMass);

ChassisMass=4TireMass=2

Page 52: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And lastly,

We need to provide a method for the player to enter the car.

I’m using a trigger method very similar to what we did with the mortar, so I’m no detail on how it works, just the differences

Etrig=spawn(class'ETrigger',self,,(RRTire.location+LRTire.location)/2);

Etrig.setbase(self);trig.SetCollision(true, false, false);

Page 53: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The TakeOver function

Now, this is mostly the same, but you may have notice that the pawn is now “hidden” when the player is driving the car.

This was done like so:

Page 54: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

The TakeOver function

//hide the original pawnuserPawn.SetOwner(userPC);userPawn.SetCollision(false, false, false);userPawn.Velocity = vect(0,0,0);userPawn.SetPhysics(PHYS_None);userPawn.SetBase(self);userPawn.bHidden=true;

userPC.bBehindView=true;Etrig.SetCollision(false, false, false);userPC.bFreeCamera = true;userPC.GotoState('EDriving');

Turn off collision and hide the pawn

Disable the trigger by turning off it’s collision

Page 55: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Which leads us to the controller

As mentioned in previous classes, new player functionality through possession requires new controllers. The same applies here.

This class has nothing other than a new state. class EController extends xPlayer;

state EDriving

Page 56: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

State EDriving

This is how the player will interface with the ECar.

Surprisingly enough, we only need 2 functions.

Page 57: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

State EDriving

Process the player movement which gets passed to:

function PlayerMove( float DeltaTime ){ ProcessDrive(aForward, aStrafe, bPressedJump); // If the vehicle is being controlled here - set replicated variables. // update 'looking' rotation - no affect on driving UpdateRotation(DeltaTime, 2);}

Page 58: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ProcessDrive

Now this is an interesting function… Starting in the parameters list.

The values that get passed in are directly set by the players input in class… PlayerInput.

ProcessDrive(aForward, aStrafe, bPressedJump);

Page 59: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ProcessDrive

Take aForward…if the player presses the up key, regardless of what key it is on the keyboard. This value will change to reflect that.

But how do we use it?

Page 60: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ProcessDrive

Well, it’s actually really easy, lets start with the jump key, our leave mechanism.

function ProcessDrive(float InForward, float InStrafe, bool InJump){ if( InJump && Role == ROLE_Authority) { ECar(pawn).LeaveCar();

return; }

Page 61: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ProcessDrive

And more interesting still is how we use the aForward.

if(InForward < -1) ECar(pawn).torque = -1;else if(InForward > 1) ECar(pawn).torque = 1;else ECar(pawn).torque = 0;

Page 62: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ProcessDrive

Essentially, depending on what InForward says, determines if we go forward or backwards.

This is then passed back into the vehicle to make the appropriate changes to Karma.

Steering uses exactly the same principle based on if the player is strafing.

Page 63: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

So, looking at how it works…

This now brings us back into the ECar class where all these updates take place.

Done in every tick to make sure that the Ecar and the Karma stay synchronised.

Page 64: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

Looking at the torque first off, based on what the controller sets the value to

if(torque>=1){ LRtire.WheelJoint.KMotorTorque= 10; RRTire.WheelJoint.KMotorTorque= 10; }else if (torque<= -1){ LRtire.WheelJoint.KMotorTorque= -10; RRTire.WheelJoint.KMotorTorque= -10; }else{ LRtire.WheelJoint.KMotorTorque= 0; RRTire.WheelJoint.KMotorTorque= 0; }

Page 65: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

The KMotorTorque is essentially how much spin we give our wheel ( based on it’s mass no doubt ).

So as we push forward, we apply momentum to the karma object and move the car.

The actual calculation of the is internal.

Page 66: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

But looking in the KCarWheelJoint class we have other values to play with too.

var(KarmaConstraint) float KMotorTorque; // torque applied to drive this wheel (can be negative)

var(KarmaConstraint) float KMaxSpeed; // max speed to try and reach using KMotorTorque (65535 = 1 rotation per second)

var(KarmaConstraint) float KBraking; // torque applied to brake wheel

Page 67: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

Essentially, this is our engine.

The Karma takes care of the specifics for us and modifies the velocity of the Ecar.

And the Steering works in a very similar manner.

Page 68: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

if(Steering>=1){ LFtire.WheelJoint.KSteerAngle=-6400; RFtire.WheelJoint.KSteerAngle=-6400; }else if (Steering<= -1){ LFtire.WheelJoint.KSteerAngle=6400; RFtire.WheelJoint.KSteerAngle-6400; }else{ LFtire.WheelJoint.KSteerAngle=0; RFtire.WheelJoint.KSteerAngle=0; }

Page 69: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

var(KarmaConstraint) float KSteerAngle; // desired steering angle to achieve using controller

(65535 = 360 deg)var(KarmaConstraint) float KProportionalGap; // for steering controller (65535 = 360 deg)

var(KarmaConstraint) float KMaxSteerTorque; // for steering controller

var(KarmaConstraint) float KMaxSteerSpeed; // for steering controller (65535 = 1 rotation per second)

Page 70: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

And we used this one to unlock the front wheels as you may recall from the InitWheels function…

var(KarmaConstraint) bool bKSteeringLocked; // steering 'locked' in straight ahead direction

LFTire.WheelJoint.bKSteeringLocked=false;RFTire.WheelJoint.bKSteeringLocked=false;

Page 71: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

ECar’s Tick

And lastly, we need to update the Karma with a call to KVehicleUpdateParams with ever tick.simulated event KVehicleUpdateParams(){

Super.KVehicleUpdateParams();// Sync params with Karma.LFTire.WheelJoint.KUpdateConstraintParams();RFTire.WheelJoint.KUpdateConstraintParams();LRTire.WheelJoint.KUpdateConstraintParams();RRTire.WheelJoint.KUpdateConstraintParams();

Page 72: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KVehicleUpdateParams

Now calling this function is interesting to say the least.

Look at where the definition takes us in the KCarWheelJoint

Page 73: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KVehicleUpdateParams

Straight into the engine. This is the only definition you will find for this…

cpptext{#ifdef WITH_KARMA virtual void KUpdateConstraintParams(); virtual void preKarmaStep(FLOAT DeltaTime);#endif}

Page 74: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

KVehicleUpdateParams

Other than in the KConstraint where you find…yup…engine.

This is another “must call” or you loose your ability to steer.

native function KUpdateConstraintParams();

Page 75: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And just for good measure

I likely don’t have to do this but I also update the mass of the objects.

KSetMass(ChassisMass);LFTire.KSetMass(TireMass);RFTire.KSetMass(TireMass);LRTire.KSetMass(TireMass);RRTire.KSetMass(TireMass);

Page 76: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

And for the last step…

We need to be able to leave the car.

Once again the core functionality of this is the same as for the mortar class….but there are some differences.

Page 77: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Leaving the car

The fires thing I do I calculate an exit location at the front of the car…and no, I don’t check to make sure that it’s safe ;-)

exitloc =(RFTire.Location+ RRTire.Location)/2;exitloc.z=exitloc.z+ 128;

Page 78: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Leaving the car

Restore collision to the trigger and pawn…

Etrig.SetCollision(true, false, false);

userPC.UnPossess();userPawn.SetLocation(exitloc);userPawn.SetCollision(true, true, true);

Page 79: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Leaving the car

Restore the physics, unhide it and take possession of the old player pawn.

userPawn.SetPhysics(PHYS_Walking);userPawn.SetBase(None);userPawn.bHidden=false;userPC.Possess(userPawn);

Page 80: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Leaving the car

And finally, make sure the playercontroller is in the right state, the free the Ecar for the next user.

userPC.GotoState('PlayerWalking');userPawn=none;//no one using the caruserPC=none;

Page 81: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

What we have is:

One functional car

Page 82: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Now for giggles

This is currently running on the defaults for the suspension and joint parameters.

Go into the CreateTire function, uncomment the parts to do with the suspension and play with the values…notice the radical differences it makes in the handling of the car.

Page 83: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Now for giggles

You can also dig other variables out of the KCarWheelJoint class (or others for that matter) and try changing them to see what happens.

Trust me you will see some amazing differences.

Page 84: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

Ok…That not a little bit.

No…that was a lot! But you should have a reasonable

understanding of what it takes to build a vehicle in UT now…from the ground up.

I’ll make mechanics out of y’all yet.

Page 85: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

But on a side note…

I also created a gametype for easy testing of the Ecar. It has no functionality other than a few exec functions for debug and summoning.

Particularly the summoning. As it stands right now, if you place the car in the world via the editor, it will not work.

Page 86: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

A side note…

The exec function “gocar” you can call from the console and it will spawn a car at the world origin.

Using the regular summon method does not work proper either. The Karma does not properly initialize.

Page 87: Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com jgiles

A side note…

Hence I’ve also included a super simple map for testing…named car.ut2.

If you choose you could also create a trigger to create the Ecar in a similar manner to how the BulldoFactory works… I leave this to you.