Search Unity

using raycasts to get information from a normal

Discussion in 'Scripting' started by Winter_XYZ, Oct 3, 2015.

  1. Winter_XYZ

    Winter_XYZ

    Joined:
    Aug 19, 2015
    Posts:
    13
    Hey

    So I'm stuck with a script involving raycasting.

    Code (csharp):
    1.  
    2.     void Update()
    3.     {
    4.         Vector3 dwn = transform.TransformDirection(Vector3.down);
    5.         if (Physics.Raycast(transform.position, dwn, 10))
    6.         {
    7.             print("The raycast has hit");
    8.         }
    9.     }
    10.  
    I need the script to detect the Y axis of the normal that the raycast is hitting and change the Y axis of the players. I've looked into raycasting in the unity API but I'm having trouble getting my head around it. Could somebody give me some help with this script?

    Thanks
     
  2. Deleted User

    Deleted User

    Guest

    First you need to get the normal from the raycast, try.
    Code (CSharp):
    1. void Update()
    2.     {
    3.         RaycastHit hitFo;
    4.         Vector3 dwn = transform.TransformDirection(Vector3.down);
    5.         if (Physics.Raycast(transform.position, dwn, out hitFo, 10))
    6.         {
    7.             print("The raycast has hit");
    8.             Vector3 cachedNormal = hitFo.normal; // Normal of the surface the ray hit
    9.         }
    10.     }
    Check: http://docs.unity3d.com/ScriptReference/Physics.Raycast.html

    The normal will be normalized meaning it's just the vector representation of direction. But if you still want to get the y-axis of the normal then cachedNormal.y;

    If you could expound on what you're trying to do I might be able to provide a better answer.
     
  3. Winter_XYZ

    Winter_XYZ

    Joined:
    Aug 19, 2015
    Posts:
    13
    Basically I want the player to "stick" to the grounds direction, the same way seen in this video. The script aligns the players gravity up with the Y axis of the normal and makes the player move in that direction.
     
  4. Deleted User

    Deleted User

    Guest

    I don't think that the script aligns the players gravity to the normal. This is what i think is happening and how I would do it. First rotate the character so that the character is standing upright according to the surface its standing on.
    Now that the character's UpVector matches that of the normal plane that its standing on we can then apply gravity according to the characters UpVector (but in the opposite direction so it pulls it down relative to character).

    Since were dealing with rotations the best solution is to use Quaternions, witch can be daunting at times because their not the easiest thing to understand.

    Here is some code that gets the job done, read the comments they explain whats happening in each part.
    Code (CSharp):
    1. RaycastHit hit;
    2. Physics.Raycast(this.transform.position, -this.transform.up, out hit, rayDist); // Your raycast
    3. Vector3 newUp = hit.normal; // cache the normal because it wil make the following code more readable
    4.      
    5. // Note: the order of a vector cross product does MATTER!   A cross B != B cross A
    6. Vector3 left = Vector3.Cross (this.transform.forward, newUp); // The cross of this.transform.forward and newUp will give you the the direction that defines your left (its the left because unity uses a left-handed system)
    7. Vector3 newForward = Vector3.Cross (newUp,left); // Take the cross of newUp and the newely found left and you will get your newForward for your character
    8. Quaternion oldRotation = this.GetComponent<Rigidbody>().transform.rotation; // Get the current rotation  (im calling oldRotation here because that is what it will be in a second)
    9. Quaternion newRotation = Quaternion.LookRotation (newForward, newUp); // Using Quaternion.LookRotation you pass in two vector3 varibales, The vector that defines forward direction and the vector the defines the upwards direction.
    Quaternion.LookRotation: http://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html

    There are two things that still need to be done. Apply the rotation then apply gravity.
    Code (CSharp):
    1. float someLerpSpeed = 1f;
    2. this.transform.rotation = Quaternion.Lerp(oldRotation, newRotation, someLerpSpeed * Time.deltaTime);
    In the code above I only applied the new rotation and didn't do any thing with gravity yet. Ill leave the implementation of gravity up to you.
     
    Last edited by a moderator: Oct 3, 2015
  5. Winter_XYZ

    Winter_XYZ

    Joined:
    Aug 19, 2015
    Posts:
    13
    What I'm going to do once this script is working and properly aligns the player with the normals is have a script that aligns the vector3 of the worlds gravity and make that the same as the players vector3 rotation.

    I've put your code in but I keep getting the error "The name 'newUp' does not exist in the current context". What would I have to define newUp as?

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class PlayerCast : MonoBehaviour
    6. {
    7.  
    8.     void Update()
    9.     {
    10.  
    11.         RaycastHit hit;
    12.         Physics.Raycast(this.transform.position, -this.transform.up, out hit, 10); // Your raycast
    13.         newUp = hit.normal; // cache the normal because it wil make the following code more readable
    14.  
    15.  
    16.         // Note: the order of a vector cross product does MATTER!   A cross B != B cross A
    17.         Vector3 left = Vector3.Cross(this.transform.forward, newUp); // The cross of this.transform.forward and newUp will give you the the direction that defines your left (its the left because unity uses a left-handed system)
    18.         Vector3 newForward = Vector3.Cross(newUp, left); // Take the cross of newUp and the newely found left and you will get your newForward for your character
    19.         Quaternion oldRotation = this.GetComponent<Rigidbody>().transform.rotation; // Get the current rotation  (im calling oldRotation here because that is what it will be in a second)
    20.         Quaternion newRotation = Quaternion.LookRotation(newForward, newUp); // Using Quaternion.LookRotation you pass in two vector3 varibales, The vector that defines forward direction and the vector the defines the upwards direction.
    21.  
    22.         float someLerpSpeed = 1f;
    23.         this.transform.rotation = Quaternion.Lerp(oldRotation, newRotation, someLerpSpeed * Time.deltaTime);
    24.  
    25.     }
    26. }
    27.  
    here's the full script. I think I've implemented everything correctly.
     
  6. Deleted User

    Deleted User

    Guest

    newUp is a Vector3, I edited my original posting to now contain the declaration of such.
     
  7. Winter_XYZ

    Winter_XYZ

    Joined:
    Aug 19, 2015
    Posts:
    13
    So in the state of my script now, how would I go about getting it to create raycasts that use the code you wrote?
     
  8. Deleted User

    Deleted User

    Guest

    What do you mean by "create raycasts that uses the code"?

    At the start of the script a raycast is generated which returns a bool if it hit any thing and will populate the hit info varible with information on the collision.

    The raycast is always being shot relative to the character so what ever the characters down direction is, is where the ray will shoot (in this instance). Rays are fired to get information about the scene that we can then act on accordingly in are scripts.
     
  9. Daydreams_5

    Daydreams_5

    Joined:
    Sep 1, 2020
    Posts:
    4
    Would you happen to know if the normals in "hitFo.normal" are normalized already?
     
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Raycast hit normals are normalized. You can check this by Debug.Log(hitFo.normal.magnitude) - it will always be 0.999 or 1 (accounting for floating point error).
     
    Daydreams_5 likes this.