don't click here

Unity3D Ground Alignment & Pathing script Stub

Discussion in 'Fangaming Discussion' started by Raz, Aug 27, 2012.

  1. Raz

    Raz

    Member
    38
    0
    0
    USA
    Here's a youtube of the build before I put the pathing in: http://www.youtube.com/watch?v=Gds9Q9z_CsY

    So a while back I was determined to get a Sonic engine working on Unity3D- it was going to be the editor I wanted to learn how to use (maybe still is). At the time, and even now, there still isn't a good Sonic controller for Unity3D, I think one or two have been made privately, but I think we're in dire need of a 3D engine by now, unfortunately, the math/physics just got the best of me- I ported this code to C# later on but I don't know what state it's in so I'm posting my unityscript backup.

    Don't expect too much :P but here's what I got working before I had exams:
    - Align to ground normal
    - Right now it only uses a single vector- but I was told (can't remember who)
    that if you use 3 vectors, you can average them and get really smooth transitions
    across every normal, instead of the snapping I have here.
    - Use the Sonic BGE (cyborg_ar) style raised-wall pathing system.
    - Basically if you raise two walls on either side of a path, the vectors
    that shoot out on either side of your character will detect them and align
    the character to the center, as well as align him to the normal of the ground.

    After this I realized I had to get the physics working- that's where I got stuck. Something about dot product of gravity and the ground normal I dunno, but my approach was going to be to say screw-it to the physics engine and handle it all in code with basic newtonian formulas that I could modify during pathing for loops and such. A friend of mine was approaching form a standpoint of guiding the physics engine along, using helper-forces.

    Personally I really wanted to do bSplines like Damizean did with Eggen but that's just so beyond me :P

    Either way, I just wanted to post this in case someone had tried it, gotten stuck, and gave up before they really had a chance to shine. I had to go to the unity channel for that axis-alignment stuff, because one function worked and another didn't and... whatever.

    I would really like to see an open source Sonic engine in Unity3D, I think it's the most approachable IDE for the beginning fangamer. SonicGDK is excellent, I'm really impressed with those guys, and I may have to bite the bullet and learn UDK, but that several gig download and high computing requirement is just overkill for what I wanted. I was happy with basic GL shading and materials, and a light footprint (not to mention Unity has a web plugin, which would make it -real- handy for SAGE).

    If it looks like I didn't know what I was doing- you're right. But at least I commented like a mofo :)

    Code (Text):
    1.  
    2. private var controller :CharacterController;
    3. controller = gameObject.GetComponent(CharacterController);
    4.  
    5. var hit : RaycastHit;       // cast a ray down from the player object
    6. var hit_left : RaycastHit;      // 2.5D Directional vector for path system
    7. var hit_right : RaycastHit;     // 2.5D Directional vector for path system
    8. var direction_vector : Vector3;
    9.  
    10. var yRot : float;       // Internal storage of direction vector because FromToRotation sets alignment axis to angle 0
    11. var playerSpeed : float = 200.0;
    12. var rotSpeed : float = 80.0;
    13. var vector_length : float = 23.0;
    14. var is2D : boolean = false;
    15.  
    16. var groundRay : Ray;
    17. groundRay = new Ray(transform.position, Vector3.down);
    18.  
    19. function FixedUpdate()
    20. {
    21.     var forward : Vector3 = transform.TransformDirection(Vector3.forward);
    22.     var down : Vector3 = transform.TransformDirection(Vector3.down);
    23.     var left : Vector3 = transform.TransformDirection(Vector3.left);
    24.     var right : Vector3 = transform.TransformDirection(Vector3.right);
    25.    
    26.     // Draw debug vectors to see wall collisions
    27.     //~ Debug.DrawRay(transform.position, down*vector_length, Color.green);     // Down vector
    28.     //~ Debug.DrawRay(transform.position, left*vector_length, Color.green);
    29.     //~ Debug.DrawRay(transform.position, right*vector_length, Color.green);
    30.  
    31.     if (Physics.Raycast(transform.position, down, hit)) {
    32.         // Keep alignment to ground.
    33.         transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);     // Get ground normal and align to it
    34.         //transform.rotation = Quaternion.LookRotation(Vector3.forward, hit.normal);        // Also works but breaks on the loop
    35.         transform.position = hit.point + transform.TransformDirection(Vector3.up*5.0);      // Move character 5.0 above the normal hit point
    36.  
    37.        
    38.  
    39.         // Begin Path System
    40.         if(Physics.Raycast(transform.position, left, hit_left, vector_length) && Physics.Raycast(transform.position, right, hit_right, vector_length)) {
    41.             //direction_vector = transform.TransformDirection((hit_left.normal - hit_right.normal)/2.0);
    42.             //direction_vector = hit_left.normal - hit_right.normal;
    43.             //direction_vector.Normalize();
    44.             //direction_vector = hit_left.point - hit_right.point;
    45.             //direction_vector.Normalize();
    46.            
    47.             Debug.DrawLine(hit_left.point, transform.position, Color.white);
    48.             Debug.DrawLine(hit_right.point, transform.position, Color.white);
    49.            
    50.             direction_vector = Vector3( hit_left.normal.x - hit_right.normal.x, hit_left.normal.y - hit_right.normal.y, hit_left.normal.z - hit_right.normal.z);
    51.             direction_vector.Normalize();
    52.             //direction_vector = Vector3.Cross(direction_vector, hit.normal);
    53.            
    54.             var midPoint : Vector3 = (hit_left.point + hit_right.point) / 2.0;
    55.             transform.Translate(midPoint-transform.position, Space.World);
    56.            
    57.             //direction_vector = transform.TransformDirection(direction_vector);
    58.             Debug.DrawRay(transform.position, direction_vector*vector_length, Color.red);
    59.            
    60.             var dirVec : Vector3 = Vector3.Cross(direction_vector, hit.normal);
    61.             Debug.DrawRay(transform.position, dirVec*vector_length, Color.blue);
    62.             //transform.LookAt(transform.TransformDirection(dirVec));
    63.             //transform.LookAt(transform.TransformDirection(direction_vector));
    64.            
    65.             // Programming note: When using transform.TransformDirection(), player gets stuck trying to point down
    66.             transform.rotation = Quaternion.LookRotation(dirVec, hit.normal);       // Points player in direction for 2D path system
    67.            
    68.             yRot = transform.rotation.eulerAngles.y;        // Make sure the last angle the player leaves the path as, is the one he's in in 3D mode, instead of returning to last 3D yRot.
    69.             }
    70.         else {
    71.             // If we don't put this in the else block, then it conflicts with the rotation genrated by 2D detection.
    72.             transform.rotation = transform.rotation * Quaternion.AngleAxis(yRot, Vector3.up);       // Reapply direction so that we can turn.
    73.             }
    74.     }
    75.    
    76.     // Note: May need to rewrite the translation step as one single statement so that it doesn't desynch the 2D controls above.
    77.     if(Input.GetKey("up")) {
    78.         transform.Translate(0.0,0.0, playerSpeed * Time.deltaTime);
    79.         }
    80.        
    81.     else if(Input.GetKey("down")) {
    82.         transform.Translate(0.0,0.0, -1 * playerSpeed * Time.deltaTime);
    83.         }
    84.     else {
    85.         controller.SimpleMove(Vector3.zero);
    86.         }
    87.        
    88.     if(Input.GetKey("left")) {
    89.         yRot = yRot + -1*200*Time.deltaTime;
    90.         }
    91.        
    92.         if(Input.GetKey("right")) {
    93.         yRot = yRot + 200*Time.deltaTime;
    94.         }
    95.    
    96. }
    97. @script RequireComponent(CharacterController)
    98.  
     
  2. Relick

    Relick

    Member
    197
    0
    16
    England
    C++/DX10 Engine (not sonic related)
    Nothing really catches my eye except for the thing about smoothing the movement with 3 vectors. Where do you get the other 2 vectors from, a front and back raycast? I've been trying to figure out how to smooth it for a while and this mightjust be it.
     
  3. Raz

    Raz

    Member
    38
    0
    0
    USA
    I would offset the the vectors from the center vector, front and back, and cast straight down. Having 2 more, one on each side, may help stabilize side to side.
     
  4. princeofknaves

    princeofknaves

    Member
    17
    0
    0
    Detroit, Michigan
    Entropy Engine, Knuckles The Echidna Game
    adjacency indices would be my guess I don't know if Unity supports that but is how I would do it.
     
  5. Relick

    Relick

    Member
    197
    0
    16
    England
    C++/DX10 Engine (not sonic related)
    So, this then?
    [​IMG]

    (obviously a side view on it, it wouldn't look like this in the actual game :P)
     
  6. Raz

    Raz

    Member
    38
    0
    0
    USA
    Yeah, nice diagram :)
     
  7. Relick

    Relick

    Member
    197
    0
    16
    England
    C++/DX10 Engine (not sonic related)
    Ok thanks, I'll try it out and get back to you.
     
  8. princeofknaves

    princeofknaves

    Member
    17
    0
    0
    Detroit, Michigan
    Entropy Engine, Knuckles The Echidna Game
    Well the EASIEST way would be to use per vertex normals and the barycentric coordinates as weighting between them that would be accurate and fairly cheap. I've been looking at the unity script reference and can't find any info if vertex normals are even stored just face normals. But if you can find something I can't it would be matter of finding sonic's position on the current triangle (there is a built in function for that) which would give you weights to interpolate the current up angle