Making a Crosshair

So I’m making a rail shooter by following the basics being taught in the course. I have created a rail using timelines. Now I want to add a crosshair that moves across the screen using the mouse. And is it possible to add a gun that sticks to the right side of the screen and points in the direction of the crosshair?

Hi,

Yes, that should be possible. For the crosshair being moved via mouse input, look up the Camera.ScreenToViewportPoint method in the API.

The rotation of the gun might be a bit trickier, so start with the crosshair and make that idea work first. For the gun, maybe the LookAt method might help. The ‘look at’ position would be the mouse position in WorldSpace coordinates or the crosshair position in WorldSpace coordinates plus an offset. Look the Camera class up in the API and check the available methods. It probably requires some maths to make your idea work if there isn’t any built-in solution in Unity.

Also please feel free to ask our helpful community of students over on our Discord chat server.

I hope this helped. :slight_smile:


[Edit:] I made a little mistake. I meant the Camera.ScreenToWorldPoint method to convert the mouse position (which is a screen position) to a world space position. Check the method names in the API carefully, so you don’t inadvertendly pick the wrong one like I did. :wink:


See also:

I tried something different. I changed my cursor to a crosshair and used this code to find the position of my cursor:

void Update()
{
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            Vector3 mousePosition = Input.mousePosition;
            Debug.Log("mouse position: " + mousePosition.x + ", " + mousePosition.y + ", " + mousePosition.z);
        }
}

Now im thinking of making a prefab of a bullet that shoots forward as soon as instantiated and instantiate it in the coords i get in mousePosition. Will that work?

I don’t see any reason why it should not work. I would say: Try to implement your idea and test it. If you manage to instantiate your bullet, the rest is probably just fine-tuning to get he desired result.

I didn’t understand the use of this function. Can you please explain in detail?

Which function do you mean? Use functions whose purpose you know and where you think that they might help you solve your problem. If you don’t understand a function, don’t use it.

this method

I tried looking it up but didn’t understand where it would be used in my project

if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            Vector3 mousePosition = Input.mousePosition;
            Quaternion CameraRotation = gameObject.transform.rotation;

            Vector3 worldPosition = Camera.main.ScreenToWorldPoint(new Vector3(mousePosition.x, mousePosition.y, 10f));

            Instantiate(bullet, worldPosition, CameraRotation);
        }

I tried something like this but this is not the effect i was going for

ezgif.com-video-to-gif (2)

If you don’t understand Camera.ScreenToViewportPoint, I would recommend to log the mouse position and the value returned by Camera.ScreenToViewportPoint into your console.

In Unity, we have 3 spaces:

  • the WorldSpace (World Unit coordinates)
  • the ScreenSpace (pixel coordinates)
  • the ViewportSpace (normalised space where the bottom left corner is (0, 0), and the top right corner is (1, 1))

If something is supposed to be in front of the camera like a GUI, you want to use the Canvas, which uses ScreenSpace coordinates for the game objects (children) and UI elements (e.g. Image instead of SpriteRenderer).

Ok but how would normalising the coords help me in this case?

I understood what it does but whats the use here?

Sorry, I probably got confused because of another student’s problem. My bad.

If you use the Canvas and an UI element for the crosshair (not the SpriteRenderer component), you could set the position of the UI element to the mouse position. You already wrote a part of the solution earlier. Then you just have to connect the crosshair UI game object with this code to make your idea work.

If you use a SpriteRenderer, the game object exists in the WorldSpace, not the ScreenSpace. In that case, you’ll have to use one of the conversion methods.

For the gun, you’ll have to do some maths, and you need the conversion methods from the Camera class. Alternatively, you could fire a raycast from the mouse position into the game world and rotate the camera towards the game object that got hit by the raycast. You’ll have to test the scenariors and define exactly what you need because ‘rotating’ is too vague, and, without any rules, the result could look ridiculous.

Right now, i directly changed the mouse pointer itself into crosshair. So you are saying instead of this, i should:

  1. Create a canvas
  2. Add an image
  3. Replace the image with a transparent pic of a crosshair
  4. Set the position of the image to the position of the mouse

After this, i have a particle system that shoots out a bullet when instantiated. How do i spawn it where i want?

I tried spawning the bullet at the coords of the crosshair (Image) and with the rotation of the camera and as expected, its spawning in the canvas. How do i fix this?

If your crosshair exists in the ScreenSpace, you’ll have to convert its screen position to a world space position. The bullets (or particle system) must not be parented to the Canvas.

You could reuse your solution with the crosshair and the mouse position but this time, you do it for the particle system game object, which is not a UI element.

Can you please explain with some example?
Like a small piece of code or a prototype?

A code suggestion (based on the code you shared here):

[SerializeField] GameObject bulletPrefab;

// a container game object in your Hierarchy
// so your Hierarchy will not become messy
// because of all those instantiated bullets;
// it must not have a parent
[SerializeField] Transform bulletParent; 

[SerializeField] RectTransform crosshair;
[SerializeField] Camera camera;

void Update()
{
    Vector3 mousePosition = Input.mousePosition;
    
    // Crosshair
    crosshair.anchoredPosition = mousePosition; // ???

    // Bullets
    if (Input.GetKeyDown(KeyCode.Mouse0))
    {
        Vector3 position = camera.ScreenToWorldPoint(mousePosition);
        Quaternion rotation = camera.rotation; // ???

        Instantiate(bulletPrefab, position, rotation, bulletParent);
    }
}

The code is not tested. Feel free to modify it according to your needs.

Regarding the code for the crosshair, this suggestion might be interesting:

Privacy & Terms