Fps//raycast | Gun not aiming the crosshair

Hi, I started with Unity two weeks ago, my apologise for the noob topic.

I’m trying to code a fps with fixed camera and moving crosshair and I’m actually coding a Raycast in order to address the bullets to the target while rotating the gun. I attached the script to the main camera, which is a child of the player as well as the gun object and the canvas containing the dynamic crosshair. Created a Ray Origin using ScreenPointToRay that takes the crosshair’s position, got the hit info out and set the range, then tried to code the gun rotation inside an if statement that consider the collider’s direction. When I press play the gun doesn’t move at all, can you please give me suggestions?

I’ve been googling and troubleshooting the whole day and can’t find a way out, it’s super frustrating.
Thank you so much for your time.

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

public class LookAtCrosshair : MonoBehaviour
{    
    public Camera fpsCam;
    [SerializeField] private GameObject gun;
    public GameObject reticle;
    private float weaponRange = 50;

    void Update()
    {
        Ray rayOrigin = fpsCam.ScreenPointToRay(reticle.transform.position);
        if (Physics.Raycast(rayOrigin, out RaycastHit hitInfo, weaponRange))
        {
            if (hitInfo.collider != null)
            {
                Vector3 direction = (hitInfo.point - gun.transform.position);
                gun.transform.rotation = Quaternion.LookRotation(direction);
            }
        }
    }
}

This is a bit guesswork on my side but is it possible that Raycast returns nothing?
If there is no object within the Raycast distance it wont be able to return true in the if statement.

If the code above is just for animation (i.e. Moving the weapon to line of sight) then use Mathf.Infinity.

Even if it is for shooting with this code you can only shoot if there is a target in the range. the range should only be used for bullet travel or damage calculation (only damaging target if it is in distance). Your code assumes that there is always a target within weaponRange so it wont work without a target.

After intense debugging I’ve found out that the Ray is actually returning values in my console so it’s working, and the gun movement has been fixed by using the localPosition of the crosshair, rotation is so much smooth.

The only problem now is that it seems the ScreenPointToRay is not detecting the canvas properly, or is not returning a proper hit point. The gun is pointing at the very upper left side of the screen all the times, while still rotating smoothly, like my screen is placed in that direction instead. So weird. And the bullets are always shot toward the center of the srceen.

How can I fix that? Adjust the canvas to my main camera doen’s seem the trick, since Render Mode is already set to Screen Space - Overlay and the crosshair work so good.

Basically the gun is following the crosshair rotation within a canvas place in the upper left side whilel bullets are still pointing at the center.

Blow the updated script.

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

public class LookAtCrosshair : MonoBehaviour
{    
    public Camera fpsCam;
    [SerializeField] private GameObject gun;
    [SerializeField] private Transform reticle;
    private float distance = 50;

    void Update()
    {
        Ray rayOrigin = fpsCam.ScreenPointToRay(new Vector2(reticle.localPosition.x, reticle.localPosition.y));
        
        Vector3 origin = new Vector3(reticle.position.x, reticle.position.y, 0);
        Vector3 forward = transform.TransformDirection(Vector3.forward) * 100;

        RaycastHit hit;

        if (Physics.Raycast(rayOrigin, out hit, distance))
        {
            print("Found an object - distance: " + hit.distance);

            if (hit.collider != null)
            {
                Vector3 direction = (hit.point - gun.transform.position);
                gun.transform.rotation = Quaternion.LookRotation(direction);
                
                Debug.Log("Le rayon frappe un objet avec le composant Plane!");
                Debug.DrawRay(origin, forward, Color.red);
            }
            else
            {
                Vector3 direction = (hit.point - gun.transform.position);
                gun.transform.rotation = Quaternion.LookRotation(direction);
                
                Debug.DrawRay(origin, forward, Color.green);
                Debug.Log("Le rayon touche un objet qui n'a pas le composant Plan!");
            }
        }
    }
}