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

Check a surfaces angle through collision

Discussion in 'Scripting' started by StarNovaRed108, Sep 19, 2022.

  1. StarNovaRed108

    StarNovaRed108

    Joined:
    Sep 19, 2022
    Posts:
    2
    Im currently making a simple ball movement script, everything works fine; however Im trying to improve the jump portion of the script. I want it to jump when its grounded(I have that part done) and when the surface its trying to jump on is a valid angle. A valid angle would be an x or z angle that isn't 90 degrees or less(could also be not -90 degrees or more). So to sum up: How can I detect the angle of a surface on a plane or a multi sided surface?

    The current code partially works, its checking the angles of the game object, not the surface its colliding with; therefore if the angle is valid you can jump on any side you collide with, and if its invalid then you cant jump on it at all.
    code:
    Code (CSharp):
    1.  public bool isGrounded = false;
    2.     public bool angleJump = false;
    3.  
    4. void Update()
    5. {
    6. .
    7. .
    8. .
    9. if(Input.GetKeyDown(KeyCode.Space) && isGrounded && angleJump)
    10.         {
    11.             rb.AddForce(jumpDir * jumpF , ForceMode.Impulse);
    12.             isGrounded = false;
    13.             angleJump = false;
    14.         }
    15. }
    16.  
    17.  
    18. private void OnCollisionEnter(Collision other)
    19.     {
    20.      
    21.         if(other.gameObject.tag == "WorldSurface")
    22.         {
    23.             isGrounded = true;
    24.             if(other.transform.eulerAngles.x<90 ||other.transform.eulerAngles.z<90||other.transform.eulerAngles.x>-90|| other.transform.eulerAngles.z>-90)
    25.         {
    26.             angleJump = true;
    27.             if(other.transform.eulerAngles.x>=90 ||other.transform.eulerAngles.z>=90 ||other.transform.eulerAngles.x<=-90 ||other.transform.eulerAngles.z<=-90 )
    28.         {
    29.             angleJump = false;
    30.         }
    31.         }
    32.        
    33.         }
    34.     }
    SurfaceAngleForumQ.png Untitled.png
    SurfaceAngleForumQ.png Untitled.png
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,773
    The first problem is using the transform rotation as the surface angle, which is why you're having trouble differentiating the two scenarios in your second image. Instead of using the transform angle, use the normal vector of the collision (e.g. the "outward pointing" direction of the specific polygon you've hit):
    Code (csharp):
    1. Vector3 surfaceNormal = other.GetContact(0).normal;
    The second problem is using Euler angles for any of this logic, because Euler angles are terrible. Instead of that, and instead of thinking in terms of X and Z angles of the rotation, you should be thinking about how far away that normal vector is from "up" (0,1,0). You can use logic that looks like this:
    Code (csharp):
    1. bool isSurfaceUpAtAll = Vector3.Angle(surfaceNormal, Vector3.up) < 90f;
     
    Kurt-Dekker likes this.
  3. StarNovaRed108

    StarNovaRed108

    Joined:
    Sep 19, 2022
    Posts:
    2
    Works Like a charm, thanks a lot for the explanation and code!