Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Having trouble creating Phycis.Raycast

Discussion in 'Scripting' started by hizral, May 11, 2012.

  1. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    Hello there,

    Im having a bit of trouble here. Im trying to create a set of raycast for my Character. I would like my Character to be able to raycast from different position which is up, down, left and right. Example is below:


    How do you do this? Any tutorial or guideline I can look into? I really don't know where to start.
     
    Last edited: May 11, 2012
  2. MADmarine

    MADmarine

    Joined:
    Aug 31, 2010
    Posts:
    627
    Ray ray = new Ray(headTransform.position, headTransform.up) //Raycast from the head upwards

    Just get the transform of the part you want to raycast from, and create a ray using Transform.up, -Transform.up (down), Transform.right etc.

    Then you just do Physics.Raycast(ray, out hit, Mathf.Infinity) or something similar and you'll cast a ray.
     
  3. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hey mate, I assume you are doing this for the platform controller we spoke about... here's the helper class I use:

    Code (csharp):
    1.  
    2.  
    3. [System.Serializable]
    4. public class RaycastCollider {
    5.     public Transform transform;
    6.     public Vector3 offset;
    7.     public float distance; 
    8.     public Direction direction;
    9.    
    10.     public bool IsColliding() {
    11.         return Physics.Raycast (transform.position + offset, GetVectorForDirection(), distance);
    12.     }
    13.    
    14.     public bool IsColliding(int layerMask) {
    15.         return Physics.Raycast (transform.position + offset, GetVectorForDirection(), distance, layerMask);
    16.     }
    17.    
    18.     public RaycastHit GetCollision() {
    19.         RaycastHit hit;
    20.         Physics.Raycast (transform.position + offset, GetVectorForDirection(), out hit, distance);
    21.         return hit;
    22.     }
    23.    
    24.     public RaycastHit GetCollision(int layerMask) {
    25.         RaycastHit hit;
    26.         Physics.Raycast (transform.position + offset, GetVectorForDirection(), out hit, distance, layerMask);
    27.         return hit;
    28.     }
    29.    
    30.     public void DrawRayCast ()
    31.     {
    32.         switch (direction) {
    33.             case Direction.DOWN: Gizmos.color = Color.green; break;
    34.             case Direction.RIGHT: Gizmos.color = Color.red;  break;
    35.             case Direction.LEFT: Gizmos.color = Color.yellow;break;
    36.             case Direction.UP: Gizmos.color = Color.magenta; break;
    37.         }
    38.         Vector3 position = transform.position + offset;
    39.        
    40.         Gizmos.DrawLine (position, position + GetVectorForDirection() * distance);
    41.     }
    42.    
    43.     private Vector3 GetVectorForDirection(){
    44.         switch (direction) {
    45.             case Direction.DOWN: return Vector3.up * -1;
    46.             case Direction.RIGHT: return Vector3.right;
    47.             case Direction.LEFT: return Vector3.right * -1;
    48.             case Direction.UP: return Vector3.up;
    49.         }
    50.         return Vector3.zero;
    51.     }
    52.    
    53. }
    54.  
     
  4. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    Thanks there JohnnyA.

    I try and understand you line of code but seem to advance for me.But I understand the concept so I did it on my own way and understanding. Hope it does what your code do.

    Here is what I've done so far:
    Code (csharp):
    1.  
    2. public var posOrigin : Transform;
    3. public var posOffset : Vector3;
    4. public var direction : Vector3;
    5.  
    6. public var isGrounded : boolean;
    7. public var isEdge : boolean;
    8. public var isWall : boolean;
    9. public var isHalfWall : boolean;
    10.  
    11. function Start ()
    12. {
    13.     posOffset = Vector3.zero;
    14.     direction = Vector3.zero;
    15. }
    16.  
    17. function Update ()
    18. {
    19.     Direction ();
    20.     DrawLine ();
    21. }
    22.  
    23. function Direction ()
    24. {
    25.     var fRight = Physics.Raycast (posOrigin.position + posOffset.right * 0.5, -direction.up, 0.85);
    26.     var bRightUp = Physics.Raycast (posOrigin.position + posOffset.up * 0.3, direction.right, 0.85);
    27.     var bRightDown = Physics.Raycast (posOrigin.position + posOffset.up * -0.3, direction.right, 0.85);
    28.    
    29.     var fLeft = Physics.Raycast (posOrigin.position + posOffset.right * -0.5, -direction.up, 0.85);
    30.     var bLeftUp = Physics.Raycast (posOrigin.position + posOffset.up * 0.3, -direction.right, 0.85);
    31.     var bLeftDown = Physics.Raycast (posOrigin.position + posOffset.up * -0.3, -direction.right, 0.85);
    32.    
    33.     var head = Physics.Raycast (posOrigin.position + posOffset, direction.up, 1);
    34.    
    35.     if (fRight  fLeft)
    36.     {
    37.         isGrounded = true;
    38.         isEdge = false;
    39.     }
    40.     else if (!fRight  !fLeft)
    41.     {
    42.         isGrounded = false;
    43.         isEdge = false;
    44.     }
    45.     else if (fRight  !fLeft)
    46.     {
    47.         isEdge = true;
    48.     }
    49.     else if (!fRight  fLeft)
    50.     {
    51.         isEdge = true;
    52.     }
    53.    
    54.     if (bRightDown  bRightUp)
    55.     {
    56.         isWall = true;
    57.     }
    58.     else if (bLeftDown  bLeftUp)
    59.     {
    60.         isWall = true;
    61.     }
    62.     else if (!bRightDown  !bLeftDown  !bRightUp  !bLeftUp)
    63.     {
    64.         isWall = false;
    65.         isHalfWall = false;
    66.     }
    67.     else if (bRightDown  !bRightUp)
    68.     {
    69.         isHalfWall = true;
    70.     }
    71.     else if (bLeftDown  !bLeftUp)
    72.     {
    73.         isHalfWall = true;
    74.     }
    75. }
    76.  
    77. function DrawLine ()
    78. {
    79.     Debug.DrawRay (posOrigin.position + posOffset.right * 0.5, direction.up * -0.85, Color.blue); //footRight
    80.     Debug.DrawRay (posOrigin.position + posOffset.up * 0.3, direction.right * 0.85, Color.blue); //bodyRightUp
    81.     Debug.DrawRay (posOrigin.position + posOffset.up * -0.3, direction.right * 0.85, Color.blue); //bodyRightDown
    82.    
    83.     Debug.DrawRay (posOrigin.position + posOffset.right * -0.5, direction.up * -0.85, Color.red); //footLeft
    84.     Debug.DrawRay (posOrigin.position + posOffset.up * 0.3, direction.right * -0.85, Color.red); //bodyLeftUp
    85.     Debug.DrawRay (posOrigin.position + posOffset.up * -0.3, direction.right * -0.85, Color.red); //bodyLeftDown
    86.    
    87.     Debug.DrawRay (posOrigin.position + posOffset, direction.up * 0.85, Color.yellow); //head
    88. }
    89.  
    It does work, all the raycast trigger check if I hit a wall or a floor down and above me.

    But having trouble with my gravity code. On my Controller.js script. I witre this line of code
    Code (csharp):
    1.  
    2. function Gravity ()
    3. {
    4.     if (ray.isGrounded)
    5.     {
    6.    
    7.     }
    8.     else
    9.     {
    10.         transform.position.y -= gravity * Time.deltaTime;  
    11.     }
    12. }
    13.  
    My character does react to the gravity but when it fall down it will go through to floor. This will only happen if I put the gravity value above 2. If I put it as 2 it will not fall through the floor but it will make the gravity not realistic. Why is this happening.
     
  5. Zethariel1

    Zethariel1

    Joined:
    Mar 21, 2012
    Posts:
    439
    Please explain what the ray variable stands for -- a character controller?

    You are altering the position, and it is easy to clip through colliders when you are changing the transform.position. If this object has a Rigidbody, use AddForce instead. Generally, try not to manipulate the transform component in physics obedient objects.

    EDIT: If you are bent on using this method however, you'll need to perform an additional raycast in the down direction, the lenght of gravity * Time.deltaTime, just to make sure you are not clipping through a collider. If there is a collision, you can just set the transform position to the collision point *(add some Y value to compensate for the object's height). If no collision, act as normal gravity does.
     
    Last edited: May 15, 2012
  6. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    all the ray variable is for my character, I dont used character controller and also not using Rigidbody. I will try you suggestion. Will update it later.

    Thank you.
     
  7. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    Thank, solve the problem. I put rigidbody inside my character and used this :
    Code (csharp):
    1.  
    2. function Gravity ()
    3. {
    4.     rigidbody.AddForce (Vector2.up * gravity);
    5. }
    6.  
    What is the different between AddForce and Velocity?

    but really like to know how JohnnyA do his character controller without using any rigidbody. But still stop the character from falling tru platform.

    and what is the optimum gravity to put, what I used now is -0.981.
     
    Last edited: May 17, 2012
  8. Zethariel1

    Zethariel1

    Joined:
    Mar 21, 2012
    Posts:
    439
    AddForce adds force to the Rigidbody, so if (for example) your body moves upwards with the force of 200, you can another 200 via AddForce.

    Velocity sets the current velocity (duh) of the object to a specific number. So should you set velocity to 200, it would become 200, no adding or substracting. It is worth noting that setting the velocity directly via script can result in unrealistic behaviours -- its better to use AddForce.

    JohnnyA basically wrote everything that the Controller class does for you -- each component can be written down to custom code to better understand and gear it towards your needs. You do however need to know what you're doing, as there are a lot of things to consider while writing a controller (physics, collisions, moving around is difficult by itself.)
     
  9. JohnnyA

    JohnnyA

    Joined:
    Apr 9, 2010
    Posts:
    5,041
    Hi hizral84,

    sorry I didn't respond, didn't see the post.

    The controller I've written does not use physics at all. It has its own physics. It calculates changes in velocity in x and y and stores them in a vector2, it then applies that velocity to the player.

    here's a little more sample code which may help:

    Code (csharp):
    1.  
    2. private void MoveInYDirection(bool grounded){
    3.        
    4.         // Apply velocity
    5.         if (velocity.y < movement.terminalVelocity) velocity.y = movement.terminalVelocity;
    6.         myTransform.Translate(0.0f, velocity.y * Time.deltaTime, 0.0f);
    7.        
    8.         // Fall/Stop
    9.         if (velocity.y <= 0.0f) {
    10.             RaycastHit hitRight = rightFoot.GetCollision(1 << backgroundLayer | 1 << passThroughLayer);
    11.             RaycastHit hitLeft = leftFoot.GetCollision(1 << backgroundLayer | 1 << passThroughLayer);
    12.  
    13.             float forceRight = (hitRight.normal * (rightFoot.distance - hitRight.distance)).y;         
    14.             float forceLeft = (hitLeft.normal * (leftFoot.distance - hitLeft.distance)).y;
    15.            
    16.             if (forceRight > forceLeft  forceRight > movement.skinSize) {
    17.                 myTransform.Translate(0.0f, forceRight - movement.skinSize, 0.0f); 
    18.                 velocity.y = 0.0f;
    19.             } else if (forceLeft > movement.skinSize) {
    20.                 myTransform.Translate(0.0f, forceLeft - movement.skinSize, 0.0f);
    21.                 velocity.y = 0.0f;
    22.             } else {
    23.                 ApplyGravity();
    24.             }
    25.         } else {
    26.             ApplyGravity();
    27.         }
    28.  
    29. <snip>
    30.  
    That version doesn't include hitting head, optimisations, or a few other niceties, but it should help with the general idea.
     
  10. hizral

    hizral

    Joined:
    Apr 27, 2010
    Posts:
    568
    Hi JohnnyA.

    Thanks for the reply.

    I manage to solved my character controller as for now using RigidBody + Gravity.

    here what i did so far:
    Code (csharp):
    1.  
    2. function Jumping ()
    3. {
    4.     if (!ray.isGrounded)
    5.     {
    6.         Gravity ();
    7.     }
    8.  
    9.     if (ray.isGrounded  !ray.isCeiling  key.jump)
    10.     {
    11.         rigidbody.velocity.y += startJump * Time.deltaTime;
    12.     }
    13.     else if (!ray.isGrounded  key.jump  (key.jumpTime < key.jumpMaxTime))
    14.     {
    15.         rigidbody.velocity.y += maxJump * Time.deltaTime;
    16.     }
    17.     else if (ray.isGrounded  ray.isCeiling || ray.isCeilingB || ray.isEdge)
    18.     {
    19.         key.jumpOn = false;
    20.     }
    21.     else
    22.     {
    23.         key.jumpOn = true;
    24.     }
    25. }
    26.  
    27. function Gravity ()
    28. {
    29.     rigidbody.AddForce (Vector2.up * gravity);  
    30. }
    31.  
    Below here is a snippet of my controller so far.


    But having a bit of trouble now, My character controller will not work with
    Code (csharp):
    1.  
    2. function OnTriggerStay (hit : Collider)
    3. {
    4.     if (hit.gameObject.tag == "TriggerAction")
    5.     {
    6.         print ("test");
    7.     }
    8. }
    9.  
     
    Last edited: May 30, 2012