Search Unity

Train along track,need to calculate perpendicular direction

Discussion in 'Scripting' started by dmaxwell, Apr 8, 2010.

  1. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    This relates to the train problem I have. It is frustrating I know it is about vectors but I just can't get it.

    So I have a simulation a cube with translation along forward direction I have a ray cast to the right (90 degrees to the direction of travel I have a rail track to the right not perpendicular to the translating box I have calculated the hit.point hit.normal The hit.normal is being shown with the draw ray it is perpendicular to the track

    To make sure the cube follows the track all I need to do is find the vector perpendicular to the hit.normal and apply this normal to the cubes transform.direction

    Any help would appreciated.
    The attachment has simple simulator
    cube represents train/carriages
    green ray -represents forward vector
    blue ray -represents hit.normal
     

    Attached Files:

  2. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    I haven't looked at the project, but finding the perpendicular vector should be straightforward:
    Code (csharp):
    1. Vector3 perp = Vector3.Cross(hit.normal, Vector3.up);
    Note that this perpendicular vector may not coincide with the direction you want the train to move in.

    If you want to get that particular vector, project the move direction onto the perp vector:
    Code (csharp):
    1. Vector3 targetDir = Vector3.Project(transform.forward, perp).normalized;
    As long as the angle between track and train are not too far off (i.e. a 90 degree difference), that should get you the perpendicular vector in the right direction.
     
  3. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    I sort of get it
    but do I take the Vector3 targetDir
    and apply it as a

    direction = transform.TransformDirection(targetDir);
     
  4. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    http://forum.unity3d.com/viewtopic.php?t=48619&highlight=train+track

    this links to other post with diagrams to show what I am trying to achieve

    It is for a game level involving a train carriages I need train driven with velocity and not animation
    An ability to alter track(signals) and slow down carriages to alter arrangement to solve game puzzle.
     
  5. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    I have a screenshot of top down view

    box represents train/carriages to the right is the rail track
    the blue line is the hit normal and the green line is the vector from the resulting dot product of hit normal and up
    What I need is the box blue facing direction to change to the green perpendicular
    line direction

    any ideas
     

    Attached Files:

  6. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    The vectors from my example were all in world space, so they should not need any modification.

    To align your blue vector with the green one use:
    Code (csharp):
    1.  
    2. transform.forward = greenVector;
    Basically transform.forward is the blue vector and can be assigned to directly.
     
  7. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    Thank you very much,indeed!

    The box is following the track nicely!!

    at the moment it jumps per section of track anyway of interpolating different vectors so I can a smooth rotation? :D

    I noticed another problem as the train goes from section to section it gets closer to track and eventually gets snagged any chance of solving it?
     

    Attached Files:

  8. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    You can do smooth rotations like this:
    Code (csharp):
    1. transform.forward = Vector3.Slerp(transform.forward, greenVector, Time.deltaTime * turnSpeed);
    turnSpeed is a float that influences how quickly the train will align with the new vector.


    Your raycast should give you the actual distance to the hit. If this value deviates from the desired distance to the track, you could use the distance, the hit normal and the Transform.Translate() function to slowly move the train back to the right distance from the track.
     
  9. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    I have fixed the issue with the train moving closer to the rail section

    I made vector = hit.pos +hit.normal * 2
    this vector was added to transfrom.position of train

    still need some way of interpolating change from one vector to another?
     
  10. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    I posted the code in new post instead of reply
    I see the slerp command but I cannot figure where it goes I already have
    transform.forward = perp;
    I am very grateful for your help so far
    CODE BELOW

    var turnSpeed: float;



    function FixedUpdate(){
    //cast ray from train to track
    direction2 = transform.TransformDirection(Vector3.right);
    var hit: RaycastHit ;
    if(Physics.Raycast (transform.position,direction2,hit,30)){
    if( hit.collider.gameObject.tag =="track") {


    // determines distance of train from track
    var Vfromtrack : Vector3;
    Vfromtrack = hit.point + hit.normal*3;

    Debug.DrawRay (hit.point,hit.normal*1, Color.blue);

    //dot product of two vectors to find perpendicular vector
    var perp: Vector3;
    perp = Vector3.Cross(Vector3.up,hit.normal);

    transform.forward = Vector3.Slerp(transform.forward, perp, Time.deltaTime * turnSpeed);
    //this gives train new direction!!!!!
    transform.forward = perp;
    //this fixes position of train so it is always a certain distance from track
    transform.position = Vfromtrack;


    //this moves train
    this.rigidbody.velocity = transform.forward * 1;


    //to show visual vector for perp
    Debug.DrawRay (transform.position, perp, Color.black);
    }
    }

    }
     
  11. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    It replaces that line.
     
  12. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    I have replaced the line
    and it is moving along but when it gets to the next track segment it jitters and get stuck
    if I increase turn speed this sometimes works?
     

    Attached Files:

  13. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    There is an (apparently problematic) dependency between transform.forward and your
    transform.TransformDirection(Vector3.right); line (note that you can also use transform.right instead of that mouthful ;) . they are equivalent).

    To remove that dependency, you could store your perp Vector3 in the class and use:
    Code (csharp):
    1. direction2 = Vector3.Cross(perp, Vector3.up);
    Instead of the current "direction2 =" line. This will make your track detector raycast ignore the animation of the turn.
     
  14. dmaxwell

    dmaxwell

    Joined:
    Nov 9, 2009
    Posts:
    24
    Still having problem with train jitter after adding line.
    Any ideas.


    Code (csharp):
    1.  
    2. var turnSpeed: float;
    3. var trainSpeed: float;
    4.  
    5.  
    6. function FixedUpdate(){
    7.  
    8.  
    9.  
    10. var hit: RaycastHit ;
    11. if(Physics.Raycast (transform.position,transform.right,hit,10)){
    12. if( hit.collider.gameObject.tag =="track") {
    13.    
    14. //dot product of two vectors to find perpendicular vector  
    15. var perp: Vector3;
    16. perp = Vector3.Cross(Vector3.up,hit.normal);
    17.  
    18. //dot product of two vectors to find
    19. direction2 = Vector3.Cross(perp, Vector3.up);
    20.                
    21. // determines distance of train from track
    22. var Vfromtrack : Vector3;
    23. Vfromtrack = hit.point + hit.normal*2;
    24. //this fixes position of train so it is always a certain distance from track
    25. transform.position = Vfromtrack;
    26.            
    27. Debug.DrawRay (hit.point,hit.normal*1, Color.blue);
    28.  
    29.  
    30. //this gives train new direction!!!!!
    31. transform.forward = Vector3.Slerp(transform.forward, [b]perp, Time.deltaTime * turnSpeed);[/b]
    32.  
    33. //this moves train
    34. this.rigidbody.velocity = transform.forward * trainSpeed;
    35.    
    36.  
    37. //to show visual vector for perp
    38. Debug.DrawRay (transform.position, perp, Color.black); 
    39. }
    40. }          
    41.    
    42. }
    43.  
    also when the train encounters left bend the train speeds up?
     

    Attached Files: