Search Unity

Follow polygon mesh normals

Discussion in 'Editor & General Support' started by antenna-tree, Oct 30, 2005.

  1. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Oh sweet irony. 10 minutes after I buy Torque and get into the private forums I discover Unity. I have been waiting for this app ever since Shockwave 3D flopped so horribly. Congratulations on what so far seems to be a killer program!

    So I'm building a simple WipeOut clone game to learn Unity and I want my floating car to hug the contour of the raceway. I know I can do this using Box Colliders over my car mesh, but I would rather have the car be independent of the dynamics gravity and just stay a fixed height above a raceway mesh so i could make roller coaster loops etc.

    Any suggestions would be great.
     
  2. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    Sorry about torque. Wish you'd seen us sooner...

    I tried to do something like that a bit over a year ago. The math were pretty horrible, and I never got it really stable enough... Anyways, here's what I did:

    The basic problem is of course figuring out what the Car's transform should be. A few hints:

    * Position the object by shooting rays down towards the track from the car's position... This does, however have some problems if the rays miss the track (and they will ;-)) It's up to you to decide if you want to shoot straight down, or down from what was down for the car in last frame....

    You'll miss the track once in a while... To minimize this, I have a few hints:

    * Use a separate game object just for the car's opinion of up down left right. Don't let the player tilt this object ever (as tilting it will move the ray collision points a lot. You make this object the parent of the player sprite, and then roll the sprite. Turning left/right could be done to the root object

    * Use a specialized piece of geometry for the ground. If your track has angled sides (like Wipeout), most likely your ground should not have this, as it will muck things up for you no end. The ground object's main purpose is to track the up area for the ground even during a jump.

    * Use a specialized piece of geometry for walls, so the player doesn't go outside the track, causing you to lose track of the ground. Consider adding a roof as well, just in case (esp if you let the player fly far)

    Even with all this, There's a fair chance you'll lose touch. What I did was simple to just let the player glide until he got over a piece of track again.

    All in all, it worked ok for me, but was a bit of a pain to get running...
     
  3. Kryptonbornson

    Kryptonbornson

    Joined:
    Oct 30, 2005
    Posts:
    1
    Same thing here. I just bought Unity yesterday after digging around the Torque forums. I've been messing with Torque for a couple of years with no real luck and no real updates in performance for Mac. Even from the tutorials, I already have an idea of what I want to do with Unity.

    I know it's off the subject, but I just had to chime in on that.
     
  4. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    Unity praise is always on topic in this forum ;-)
     
  5. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Thanks Nicholas! That is what I was looking for. I did a search on the forums for Raycast and found a snippet that at least has started me in the right direction.

    Code (csharp):
    1.  
    2.  
    3. // cast a ray down from the player object
    4. var hit : RaycastHit;
    5.  
    6. function Update () {
    7. if (Physics.Raycast (transform.localPosition, transform.TransformDirection (Vector3.down), hit)) {
    8. //if (Physics.Raycast (transform.localPosition, Vector3.down, hit)) {
    9. // put the player object where the ray hit the terrain object
    10. transform.localPosition = hit.point;
    11. // orient the player object with the terrain surface normal
    12. // only change the X and Z axes, since the Y-axis is rotated by the player
    13. transform.localRotation = Quaternion.FromToRotation (Vector3.up, hit.normal);
    14.  
    15. }
    16. }
    17.  
    18.  
    This orients the object with the polygon normals correctly, but as soon as it reaches an angle change it passes right through the mesh. I think it would work if instead of the Raycast going to the "hit.point" it went to the "hit.point" plus a very small distance in the up normal direction. Then it would be guaranteed to correctly Raycast on the next Update because it would be in a constant state of "falling".

    I'm very new to all this so could someone please help me with the little bit of code I need to add to this line:

    transform.localPosition = hit.point;

    Thanks for helping out a newbie.
     
  6. hangt5

    hangt5

    Joined:
    Oct 26, 2005
    Posts:
    26
    transform.localPosition = hit.point + (Vector3.up * Height);
     
  7. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    The above code will actually move the player up in worldspace. This is well and good for flat surfaces, but will crap out on you pretty quickly when making a loop...

    Instead, try:

    Code (csharp):
    1.  
    2. transform.localPosition = hit.point + (hit.normal * Height);
    3.  
    This will make the car move away from whatever it hit (which should be what you're looking for.

    Also, I'm not sure how your transform.localRotation will stand handle itself in the loop case - I would recommend using Quaternion.LookRotation using the player's forward vector in last frame;

    Sth like this:
    Code (csharp):
    1.  
    2. transform.rotation = Quaternion.LookRotation (Transform.TransformDirection (Vector3.forward), hit.normal;
    3.  
     
  8. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Thanks again Nicholas and hangt5. I'm very shaky with the syntax stuff right now, but I changed hangt5's snippet to:

    Code (csharp):
    1.  
    2. transform.localPosition = hit.point + (transform.TransformDirection (Vector3.up * 0.5));
    3.  
    This now works great and the car no longer goes through the mesh, even on loops and twists! Now to get my Camera to follow the action a little better.

    This stuff is way too much fun!!!
     
  9. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    Just a quick question about Nicholas' use of the term "last frame"... How do you call this? Is it LateUpdate vs Update? Is there another function "LastUpdate"? Right now I'm putting my whole car control script into one function Update just so I can be positive of what happens first.
     
  10. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    First off, if you're doing anything with physics, you should use FixedUpdate and not Update...

    And by using last frame's position, I simply mean using the value figured out in last call of the function.

    The Update functions were thought like this:
    FixedUpdate: Anything that works on physics...
    Update: Misc small behaviour (lights pulsing, etc)
    LateUpdate: Called just before rendering... Used mainly to move a camera into the correct position.