Rotating raycasts with a GameObject and keeping them from spacing out from each other

Hello, I’m currenly facing a problem with rotating raycasts along with an object in my game. I’ve made a placeholder model of a horse and I’m firing 5 rays from underneath him. I also have a camera attached to it that I’ve used for it’s movement. For testing purposes I’ve created 5 basic cubes with a material on them to track all 5 hit points of these rays. All of these components are inside a single parent object called “HorseParent”. I have a script on the “Player” object that mounts the player onto the horse via a raycast. When mounted the “Player” object becomes a child of the HorseParent" object. Now for the real problem.


I’m firing the rays from a single origin and they rotate with the horse just fine, but when the Y position of the horse changes the rays start to space out from each other. I’ve tried to fix this by offsetting the origins of the rays so that all of them are a straight line down from the horse. But for some reason this affects the rotating of the rays and it either makes the red test cubes rotate in one place or just around some imaginary point set by the size of the offset.


I’ve found out that the problem is probably in the “horse.transform.parent.forward”, because once the offset on the z axis is 0 the rotation works fine, but once there is an offset via a new Vector3 the problem above occurs. I just can’t figure out how to fix this. Can anyone help?
Here is the code i wrote:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class horseContoller : MonoBehaviour
{
    public GameObject player; 
    private GameObject horse;
    public Transform cam;
    private bool rayHit;
    private bool isMounted = false;
    private float maxDistance = 100f;
    private Vector3 playerScale;
    public Transform frontCam;
    public LayerMask ground;
    float moveSpeed = 10f;
    public GameObject cube1, cube2, cube3, cube4, cube5;
    
    // Start is called before the first frame update
    void Start()
    {
        playerScale = player.transform.localScale;
    }

    // Update is called once per frame
    void Update()
    {       
        RaycastHit ray;
        Ray ray1 = new Ray(frontCam.transform.position, frontCam.transform.forward);
        rayHit = Physics.Raycast(cam.position, cam.TransformDirection(Vector3.forward), out ray, 1.8f);            

        if (Input.GetKeyDown(KeyCode.E) && rayHit && !isMounted)
        {
            horse = ray.transform.gameObject;
            player.transform.parent = horse.transform.parent;
            player.transform.position = horse.transform.position + new Vector3(0, 1, 0);
            player.GetComponent<movement>().enabled = false;
            isMounted = true;
        }
        else if (Input.GetKeyDown(KeyCode.E) && isMounted)
        {
            player.transform.parent = null;
            player.transform.localScale = playerScale;
            player.GetComponent<movement>().enabled = true;
            isMounted = false;
        }

        if (isMounted)
        {
            RaycastHit hit1, hit2, hit3, hit4, hit5;
            //od hlavy dozadu
            Ray rayDown1 = new Ray(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up + (horse.transform.parent.forward * 1.2f)); //horse.transform.parent.localPosition + new Vector3(0, -1, 0))
            Ray rayDown2 = new Ray(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up + (horse.transform.parent.forward * 0.6f));
            Ray rayDown3 = new Ray(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up);
            Ray rayDown4 = new Ray(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up - (horse.transform.parent.forward * 0.6f));
            Ray rayDown5 = new Ray(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up - (horse.transform.parent.forward * 1.2f));  
            
            Physics.Raycast(rayDown1, out hit1, maxDistance, ground);
            Physics.Raycast(rayDown2, out hit2, maxDistance, ground);
            Physics.Raycast(rayDown3, out hit3, maxDistance, ground);
            Physics.Raycast(rayDown4, out hit4, maxDistance, ground);
            Physics.Raycast(rayDown5, out hit5, maxDistance, ground);

            //horse.transform.parent.Rotate(0,0.5f,0 * Time.deltaTime);
            /*
            Debug.DrawLine(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up + (horse.transform.parent.forward * 1.2f), Color.blue);
            Debug.DrawLine(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up + (horse.transform.parent.forward * 0.6f), Color.blue);
            Debug.DrawLine(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up, Color.blue);
            Debug.DrawLine(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up - (horse.transform.parent.forward * 0.6f), Color.blue);
            Debug.DrawLine(horse.transform.parent.position + new Vector3(0, -0.5f, 0), -horse.transform.parent.up - (horse.transform.parent.forward * 1.2f), Color.blue);
            */

            Debug.Log("Front: " + hit1.distance + " MidFront: " + hit2.distance + " Mid: " + hit3.distance + " MidBack: " + hit4.distance + " Back: " + hit5.distance);    
            
            cube1.transform.position = hit1.point;           
            cube2.transform.position = hit2.point;
            cube3.transform.position = hit3.point;
            cube4.transform.position = hit4.point;
            cube5.transform.position = hit5.point;

            //Debug.Log(hit1.collider.name);

            if (Input.GetKey(KeyCode.W))
            {                             
                horse.transform.parent.position = horse.transform.parent.position + ray1.direction * moveSpeed * Time.deltaTime;
            }

            if (Input.GetKey(KeyCode.W) && Input.GetKey(KeyCode.LeftShift))
            {
                horse.transform.parent.position = horse.transform.parent.position + ray1.direction * moveSpeed * 1.5f * Time.deltaTime;
            }

            if (Input.GetKey(KeyCode.S))
            {
                horse.transform.parent.position = horse.transform.parent.position + ray1.direction * -moveSpeed * Time.deltaTime;
            }
            
            if (Input.GetKey(KeyCode.A))
            {
                horse.transform.parent.Rotate(-Vector3.up * 70 * Time.deltaTime);
            }

            if (Input.GetKey(KeyCode.D))
            {
                horse.transform.parent.Rotate(Vector3.up * 70 * Time.deltaTime);
            }
        }
    }
}

Here are some examples of the problems:

205113-gif2.gif
205114-gif3.gif

The issue you are facing is caused by the rotation of the raycasts, which is affected by the position of the parent object and its forward direction. As you mentioned, when the Y position of the horse changes, the raycasts space out from each other because the forward direction of the parent object changes.
To fix this, you need to ensure that the raycast origin is always aligned with the forward direction of the parent object, regardless of its position. You can do this by using a combination of the parent object’s position and rotation to calculate the raycast origin.