How am I able to utilize Mouse.Target through UserInputService?

When encountering the documentation for mouse, there was a disclaimer as follows:

Mouse has been superseded by UserInputService and ContextActionService , which cover a broader scope, are more feature rich, and support cross-platform patterns better. It remains supported because of its widespread use, but you should strongly consider using these alternatives.

I’d like to stay up to date with new features that the Wiki suggests, but how exactly am I able to get to the mouse and then to its target? I did trying following through, but the script gives me an error.

A basic test function where if you click a BasePart of sort, it will randomly change a color.

-- LocalScript inside StarterGui
local UIS = game:GetService("UserInputService")

UIS.InputBegan:Connect(function(input,gameProcessed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		local target = input.Target
		if target:IsA("BasePart") then
			target.BrickColor = BrickColor.Random()
		end
	end
end)


What am I doing wrong?

1 Like

There is no built in function or property for Mouse.Target with the UserInputService InputObject, but you can find it using Ray’s as demonstrated in this post.

I have a module called PlayerMouse2 which is an alternative to the legacy PlayerMouse instance. It gets the target through UserInputService as well as raycasting and exposes api for a few more things if you just want something that works. (PlayerMouse2.Target)

But if you want to know how you can do this, then let me explain.

First you will want the X and Y (2D) coordinates of the mouse. You can get them using UserInputService:GetMouseLocation which returns a Vector2 describing this.

local mouse_location = UIS:GetMouseLocation()

Then you want to create a ray from those coordinates using Camera:ViewportPointToRay.

local unscaled_ray = camera:ViewportPointToRay(mouse_location.X, mouse_location.Y - 36)

Great! Now we have a Ray object. Now we want to extend this ray to 1000 studs because that is what was the length iirc.

local result = workspace:Raycast(unscaled_ray.Origin, unscaled_ray.Direction*1000)

Now we got a RaycastResult.

Then we check if the ray hit something.

local target
if result then
    target = result.Instance
end

There we go! Now you have the Target. This is also a way to get the position from mouse.Hit through the Position field of RaycastResult :grin:

5 Likes

Why is it more difficult to get to the mouse’s Target? If Roblox insists on developers using a different service but don’t bother to add a property for Target/Hit, how is this exactly beneficial?

I’m not familiar with Raycasting either, so these responses are bit out of my field. Has Roblox ever announced whether they would be deprecating Mouse?

3 Likes

Mouse is not deprecated, at the moment it is just legacy, although i imagine it being deprecated in the next few years. I don’t believe explanations provided are too complex, i think it would be good if you showed what you didn’t understand so we can break it down for you.

2 Likes

Well I’m not keen on Raycasting itself or these two lines here:

local unscaled_ray = camera:ViewportPointToRay(mouse_location.X, mouse_location.Y - 36)

local result = workspace:Raycast(unscaled_ray.Origin, unscaled_ray.Direction*1000)

I’m just not sure how I’d be able to incorporate this into my script.

And this part:

local target
if result then
    target = result.Instance
end

Is it asking if the target is an instance or not? If I changed it to result:IsA("BasePart"), would that make a difference?

I’ll be reading the Intro to RayCasting article over again to see if it’ll make sense to me.

1 Like

This line right here is starting the ray wherever the mouse on the X and Y is. I subtract 36 because this method accounts for the topbar inset on the Y which is 36 pixels. So I remove that accommodation by doing that.

You see where my mouse is pointing, that is where the ray will be casted from.

WorldRoot:Raycast returns nil if the ray didn’t hit anything, so i just check that it did so we can get the Instance property of the returned RaycastResult, which is what is returned by WorldRoot:Raycast.

3 Likes

Also, note that if you want it to work on Touch enabled device you will have to use the TouchTapInWorld event and raycast from the screen point, just letting you know because Mouse.Target does work on all platforms but, for the UserInputService you will have to do it for each individual one.

3 Likes

Wanted to update this thread incase anybody stumbled upon it for their own researching findings; I came across a bug that gives total inaccuracies to the target of the Mouse. (Moreso, the ray, but ah tomayto, tomahto.)

In other words, the ray will give inaccurate results due to the inset for the top bar being included. (36 pixels to be specific.) As I kept testing I knew something was off with the Mouse and figured this out 3/4ths of development in my game. (Thankfully did not release it with this surprise :laughing:)

Anyhow, I changed the line to this:

local unscaled_ray = camera:ViewportPointToRay(mouse_location.X, mouse_location.Y)

Instead of:

local unscaled_ray = camera:ViewportPointToRay(mouse_location.X, mouse_location.Y - 36)

Which gave more pleasing results.

Before, it gave unappealing and displeasurable results:

2 Likes

Okay so I find using UserInputService:GetMouseLocation() instead input.Position was more accurate

local mouseLocation = UIS:GetMouseLocation()
local unscaled_ray = camera:ViewportPointToRay(mouseLocation.X,mouseLocation.Y)
local result = workspace:Raycast(unscaled_ray.Origin, unscaled_ray.Direction*1000)

I’m not sure if your reply is a statement or in need of clarification, so I’m going to assume the latter.

Essentially, yes, because :GetMouseLocation() gathers the X and Y coordinates of the mouse. (Which is essentially the same thing as the legacy term involved, Mouse.Target because it functions that same way.)