Mouse World Position

i would like to understand more why you put the method static the sound wasnt clear. can you please share with me this info?

Making the method static makes it possible to call it from anywhere without needing to find the Mouse World instance. It’s simply a convenience.

1 Like

I was going to write something like this, but after looking at the code I found that the MouseWorld class is a singleton and there is no real need for this method to be static. I can’t remember if we initially had this as just a class with the static method and then later refactored it into a singleton because we wanted to specify the ‘mouse plane layer mask’ in the inspector and never changed the method. In either case, is allows us to call it without finding/holding a reference to the instance.

1 Like

I’ll do you one better. You don’t need an instance. You don’t even need an actual instantiated MouseWorld…

Here’s mine:

MouseWorld.cs
using UnityEngine;

public class MouseWorld : MonoBehaviour
{
    [SerializeField] private LayerMask layerMask;

    private static LayerMask mask=0;
    private static LayerMask Mask
    {
        get
        {
            if (mask == 0) mask = 1 >> LayerMask.NameToLayer("MousePlane");
            return mask;
        }
    }
    
    private void Awake()
    {
        mask = layerMask;
    }
    
    public static Vector3 GetPosition()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, mask))
        {
            return hit.point;
        }
        return Vector3.zero;
    }
    
    public static (bool, Vector3) TryGetPosition()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        return (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, mask), hit.point);
    }
}

If there is no MouseWorld GO, then the LayerMask is automagically set to look up the layer from LayerMask.NameToLayer() method. Otherwise, if there is a MouseWorld GO, then all it does is set the static LayerMask to the serialized LayerMask. Everything else is static, and it includes both a standard method and a TryGet style method because… well… because.

2 Likes

This is kinda what I thought it was until I looked at the code. I forgot we wanted the layer mask. I thought we had something like this (I added some things in-case)

public class MouseWorld
{
    public static Vector3 GetPosition(LayerMask mask)
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, mask))
        {
            return hit.point;
        }
        return Vector3.zero;
    }

    public static Vector3 GetPosition(Camera camera, LayerMask mask)
    {
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, mask))
        {
            return hit.point;
        }
        return Vector3.zero;
    }
}

There is no state being kept, so there is no need to have an instance.

Yeah, if you cut out the Layermask altogether and make it be passed from the calling object, there is no need for a state at all… Then you can make the class itself static and remove the MonoBehaviour.

Apologies to @Hamam for completely going off into the woods on this topic…

1 Like

I could (should) clean that up and call the second from the first to reduce duplicated code

public class MouseWorld
{
    public static Vector3 GetPosition(LayerMask mask)
    {
        return GetPosition(Camera.main, mask);
    }

    public static Vector3 GetPosition(Camera camera, LayerMask mask)
    {
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, mask))
        {
            return hit.point;
        }
        return Vector3.zero;
    }
}

Absolutely. I will end here…

1 Like

My final rendition:
Removed the TryGetPosition because I never used it. Kept the mask, as a fallback in case the mask is omitted). This can be called with or without a LayerMask parameter.

using UnityEngine;

public static class MouseWorld 
{
    private static LayerMask mask=0;
    private static LayerMask Mask
    {
        get
        {
            if (mask == 0) mask = 1 >> LayerMask.NameToLayer("MousePlane");
            return mask;
        }
    }
    public static Vector3 GetPosition(LayerMask layerMask = new())
    {
        if (layerMask == 0) layerMask = Mask;
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, layerMask))
        {
            return hit.point;
        }
        return Vector3.zero;
    }
}
1 Like

I made it static just for ease of use so you can just do MouseWorld.GetPosition(); instead of MouseWorld.Instance.GetPosition(); since that is the only purpose of that class.

That’s really it. If you prefer making it a regular singleton then that would work just the same.

And yup like Brian posted you could indeed just make it entirely static, set up the mask through code and you don’t even need the object in the scene.

As always there’s tons of options for solving any problem.

1 Like

Thanks a lot for your respond. and for the others who are trying to clear the things. i really appreciate it

Thanks Brian i really appreciate your help and the info you send were great

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms