using raycasts to get information from a normal

Hey

So I’m stuck with a script involving raycasting.

    void Update()
    {
        Vector3 dwn = transform.TransformDirection(Vector3.down);
        if (Physics.Raycast(transform.position, dwn, 10))
        {
            print("The raycast has hit");
        }
    }

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

First you need to get the normal from the raycast, try.

void Update()
    {
        RaycastHit hitFo;
        Vector3 dwn = transform.TransformDirection(Vector3.down);
        if (Physics.Raycast(transform.position, dwn, out hitFo, 10))
        {
            print("The raycast has hit");
            Vector3 cachedNormal = hitFo.normal; // Normal of the surface the ray hit
        }
    }

Check: Unity - Scripting API: Physics.Raycast

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.

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.

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.

RaycastHit hit;
Physics.Raycast(this.transform.position, -this.transform.up, out hit, rayDist); // Your raycast
Vector3 newUp = hit.normal; // cache the normal because it wil make the following code more readable
     
// Note: the order of a vector cross product does MATTER!   A cross B != B cross A
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)
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
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)
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.

float someLerpSpeed = 1f;
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.

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?

using UnityEngine;
using System.Collections;

public class PlayerCast : MonoBehaviour
{

    void Update()
    {

        RaycastHit hit;
        Physics.Raycast(this.transform.position, -this.transform.up, out hit, 10); // Your raycast
        newUp = hit.normal; // cache the normal because it wil make the following code more readable


        // Note: the order of a vector cross product does MATTER!   A cross B != B cross A
        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)
        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
        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)
        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.

        float someLerpSpeed = 1f;
        this.transform.rotation = Quaternion.Lerp(oldRotation, newRotation, someLerpSpeed * Time.deltaTime);

    }
}

here’s the full script. I think I’ve implemented everything correctly.

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

So in the state of my script now, how would I go about getting it to create raycasts that use the code you wrote?

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.
Raycast: http://docs.unity3d.com/ScriptReference/Physics.Raycast.html

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.

Would you happen to know if the normals in “hitFo.normal” are normalized already?

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).

1 Like