Detecting when a mouse moves off an object?

I am currently using Mouse.Move for a piece of code I am trying to achieve. Is it possible to detect when a mouse moves on/off an object rather than using move?

What I am trying to achieve is when the mouse hovers over a door, a selection box will appear over the door, but when moved off it will be deleted.

Is that possible or will I have to use Move?

3 Likes

You could place a SurfaceGui on the door and listen to the MouseEnter / MouseLeave events on a transparent Frame contained within it.

2 Likes

Another way I think would work would be using Mouse.Target to check if the mouse is on a part of the door. Create the selection box if it is and then destroy it if it isn’t.

2 Likes

Thank you guys, I’ll try out both now.

I personally would use a click detector since that has some sort of mouse enter / mouse leave property and can also be managed on server, also working with ui I find repetitive and boring.

1 Like

This still requires a loop-driven mechanism, whilst the user is looking for an event-driven one.

I’d probably use the MouseHoverEnter and MouseHoverLeave events of a ClickDetector. If you parent a ClickDetector to a model, then the ClickDetector functionality will be applied to the model as a whole (the events will fire after you mouse over/off any part of the model; but not multiple times for each part)

1 Like

Using ClickDetector.MouseHoverEnter and ClickDetector.MouseHoverEnter should work, just parent it to the door model.

1 Like

First of all, use a LocalScript with RunService.RenderStepped instead, because it will update every frame instead of every time the mouse is moved. If the player moves and the mouse doesn’t, it won’t update.

Here’s a quick example:

local was = nil
local mouse = game.Players.LocalPlayer:GetMouse()
local runService = game:GetService("RunService")

while true do
    if(mouse.Target.Name == "PartToEffect") then  -- Or you could check the parent
        if(was ~= nil) then
            was:Destroy()
            was = nil
        end
        was = Instance.new("SelectionBox")
        was.Adornee = mouse.Target
        was.Parent = mouse.Target
    else
        if(was ~= nil) then
            was:Destroy()
            was = nil
        end
    end
    runService.RenderStepped:Wait()
end

This is what I’ve used in all of the cases I’ve needed to make a SelectionBox on hover.

If you want the default mouse cursor, it’s more of a pain.

the PlayerMouse.Target seems the best choice, it has no visual effect on this mouse, one can be added with own logic, own decals etc, and it gives the behaviour wanted.

local mouse = game.Players.LocalPlayer:GetMouse()
local DoorModel = workspace:WaitForChild("Door")--put in your model workspace path here
local Box = Instance.new("SelectionBox")
Box.Parent = workspace
game:GetService("RunService").RenderStepped:Connect(function(dT)
    if mouse.Target:IsDescendantOf(DoorModel) then
        Box.Adornee = mouse.Target
    else
        Box.Adornee = nil
    end
end)

Just iterating on one of the above answers a bit, there’s no reason to create new selectionboxes in renderstepped which could be performance expensive, cheaper to have one already made, store a reference and just set the Adornee property.

RenderStepped blocks frames from rendering. You should never use RenderStepped without good reason, such as for updating something in tandem with the camera. Look towards Heartbeat (post-physics simulation) and Stepped (pre-physics simulation) instead.

cc @Madchap32 @fret13103

1 Like
(See below)

I don’t believe that this is the case or has ever been the case. Events are run asynchronously and I often run into issues with the RenderStepped connection actually firing on top of itself rather than the event being too slow. If RenderStepped blocks frames from being rendered calling wait(1) should reduce the framerate to one, but this is obviously not the case.

If by blocks frames from rendering you mean due to the CPU being overused than yes definitely, but Heartbeat won’t save you here, you’ll simply be hitting CPU limits in general and it has nothing to do with the event being RenderStepped related.

Edit: The Heartbeat vs Stepped information is new to me and is definitely useful. I actually assumed that Stepped was something separate to physics

Please ignore my last post, it was somewhat misleading and misinformed.

RenderStepped blocks the execution of steps, not necessarily frames from being rendered. It’s better to read a few of the linked posts in the following posts since they explain it better than I do:

(Diagram of how RunService events are executed)

(Explanation of RenderStepped and its impact)

1 Like

Right, thanks. I’ll make an edit.