Raycast question - RaycastHit.Normal usage ?

So, I have the following code

            // Raycast to check if we have hit obstacle at the front of player
            Ray rayF = new Ray(transform.position, transform.forward);
            Vector3 forward = transform.TransformDirection(Vector3.forward) * raycastLinesize;
            Debug.DrawRay(transform.position, forward, Color.green);
            if (Physics.Raycast(rayF, out RaycastHit hitF, raycastLinesize))
            {
                if (hitF.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Front!");
                    keyU = false;
                }
            }
            else
            {
                keyU = true;
            }

            // Raycast to check if we have hit obstacle at the back of player
            Ray rayB = new Ray(transform.position, -transform.forward);
            Vector3 backward = transform.TransformDirection(Vector3.back) * raycastLinesize;
            Debug.DrawRay(transform.position, backward, Color.green);
            if (Physics.Raycast(rayB, out RaycastHit hitB, raycastLinesize))
            {
                if (hitB.collider.tag.Equals("Wall"))
                {
                    Debug.Log("You Hit A Wall With The Back!");
                    keyD = false;
                }
            }
            else
            {
                keyD = true;
            }

// RayL and RayR also....

I do this 4 times for each direction on my cube object ( don’t need top and bottom ), front, back, left and right. Although it works, it seems messy and it’s bothering me, I’ve not worked in depth with RaycastHit.Normal, but it seems like it would provide a better solution to the problem than my current script, has anyone done anything similar to my script but using RaycastHit.Normal instead ? A code sample or some basic instruction would be greatly appreciated to help me condense my code a little.

Thanks.

One way to reduce this sort of boilerplate code is to identify what changes from each direction.

In this case it might only be the direction of your cast, and perhaps of your subsequent decision.

You can put those directions in an array and the iterate them with a for() loop:

Vector3[] Directions = new Vector3[] { transform.forward, transform.right, -transform.forward, -transform.right};

Now you can spin through the four entries in the Directions array and do the same bit of logic again and again.

In your case you might want a more complex structure than just a Vector3, since you want to know which key to un-press. Or you can just make two lists, one for the direction and one for “what do I set to false or true” for example. Since the keyU fields are probably booleans, you need to make a little delegate to set them, such as this

System.Action<bool> SetKeyU = (tf) => { keyU = tf; }

etc for each direction

and you can put those four delegates in a table and call them with true/false to set your keyU, keyD, etc., something like:

        System.Action<bool> SetKeyU = (tf) => { KeyU = tf; };
        System.Action<bool> SetKeyD = (tf) => { KeyD = tf; };

        var ResultDelegates = new System.Action<bool>[] {
            SetKeyU,
            SetKeyD,
        };
1 Like

Thanks, @Kurt-Dekker
Very in depth, thanks for the reply, I’ll see if I can figure it out based on what you have said.
In the interim, I found the following script when researching other questions on the subject, it kind of does what I want, but I need to re-engineer it for my needs.

using UnityEngine;

public class GetSideHit : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log(ReturnDirection(collision.gameObject, this.gameObject));
    }

    private enum HitDirection { None, Top, Bottom, Forward, Back, Left, Right }
    private HitDirection ReturnDirection(GameObject Object, GameObject ObjectHit)
    {
        HitDirection hitDirection = HitDirection.None;
        Vector3 direction = (Object.transform.position - ObjectHit.transform.position).normalized;
        Ray MyRay = new Ray(ObjectHit.transform.position, direction);

        if (Physics.Raycast(MyRay, out RaycastHit MyRayHit))
        {
            if (MyRayHit.collider != null)
            {
                Vector3 MyNormal = MyRayHit.normal;
                MyNormal = MyRayHit.transform.TransformDirection(MyNormal);

                if (MyNormal == MyRayHit.transform.up) { hitDirection = HitDirection.Top; }
                if (MyNormal == -MyRayHit.transform.up) { hitDirection = HitDirection.Bottom; }
                if (MyNormal == MyRayHit.transform.forward) { hitDirection = HitDirection.Forward; }
                if (MyNormal == -MyRayHit.transform.forward) { hitDirection = HitDirection.Back; }
                if (MyNormal == MyRayHit.transform.right) { hitDirection = HitDirection.Right; }
                if (MyNormal == -MyRayHit.transform.right) { hitDirection = HitDirection.Left; }
            }
        }
        return hitDirection;
    }
}
1 Like