1 / 87

Sega 500

Sega 500. Building a Vehicle. Jeff “Ezeikeil” Giles jgiles@artschool.com http://gamestudies.cdis.org/~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!. No small task.

hovan
Download Presentation

Sega 500

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Sega 500 Building a Vehicle Jeff “Ezeikeil” Giles jgiles@artschool.com http://gamestudies.cdis.org/~jgiles

  2. 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!

  3. 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.

  4. 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++.

  5. 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.

  6. 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.

  7. 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.

  8. 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.

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

  10. 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.

  11. 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.

  12. 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

  13. 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.

  14. Naming the bones • Also, make sure they have appropriate names. • This is how we will know where to attach the wheel…this is important.

  15. 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!

  16. 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…

  17. 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.

  18. 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.

  19. 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…

  20. 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:

  21. Smoke and mirrors Where the yellow is the collision volume.

  22. 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…

  23. A trick of the light • We actually have another object…a 16,16,16 cube…which IS a static mesh. Static mesh Collision volume

  24. 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?

  25. 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.

  26. 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.

  27. 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?

  28. 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 }

  29. 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();

  30. 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!

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

  32. 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; }

  33. 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)

  34. 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);

  35. 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…

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

  37. 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.

  38. CreateTire tire.KGetRigidBodyState(ks); ks.Position.Z-=140; // ugh...magic number....bad...no twinkie! pos=KRBVecToVector(ks.Position); • 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…

  39. 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; };

  40. KrigidBodyState • What would happen is these collision volumes (green) would fly away from the tire…really weird. • Like I said…Hours.

  41. KrigidBodyState tire.KGetRigidBodyState(ks); ks.Position.Z-=140; // ugh...magic number....bad...no twinkie! pos=KRBVecToVector(ks.Position); • 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.

  42. KrigidBodyState • This is what happens if I don’t use it… The Wheels collision Wheel

  43. 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!

  44. 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);

  45. 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.

  46. 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…

  47. 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

  48. CreateTire tire.WheelJoint.KPos1 = pos/50; // scale collision params of //wheel to car tire.WheelJoint.KConstraintActor1 = self; tire.WheelJoint.KConstraintActor2 = tire; • 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.

  49. 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);

  50. 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 );

More Related