Hello! I’m trying to make an E to interact system that only works while the mouse is hovering over an interactable. However, i’m having difficulty figuring out how to go about it. I’ve messed around with a script for a while and can’t figure out how to make it work.
I’ve looked around on the forum and all the solutions are content with using proximity prompts, but i’m quite certain i want a hover-over keybind system. It fits what i’m making.
Here’s my current local-code:
local players = game:GetService("Players")
local uis = game:GetService("UserInputService")
clickdetector = script.Parent.ClickDetector
hover = script.Hovering
--detect keypress while hovering, fire event
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.E and hover.Value == true then
script.Parent.Pressed:FireServer()
end
end)
--set hover to true while hovering, make interact gui visible
if clickdetector.MouseHoverEnter then
hover = true
players.LocalPlayer.PlayerGui.Main.Interact.Visible = true
end
--set hover to false when leaving hover, make interact gui invisible
if clickdetector.MouseHoverLeave then
hover = false
players.LocalPlayer.PlayerGui.Main.Interact.Visible = false
end
Here’s my current server-code:
debounce = script.Parent.Debounce
enabled = script.Parent.Enabled
pressed = script.Parent.Pressed
click = script.Parent.Click
--when local detects a press, do stuff
pressed.OnServerEvent:Connect(function()
if enabled == false then
script.Parent.Material = "Neon"
enabled = true
else
script.Parent.Material = "Plastic"
enabled = false
end
click:Play()
end)
Apologies, i’m pretty new.
The only loop i’m aware of right now is while true do, and i’m not sure all of my buttons should be checking every second if i’m hovering over them. What loop should i use here?
Been messing around with this, and i’m starting to think i should make some kind of “interactable handler” instead, if i’m gonna need tons of interactables checking if you’re hovering over them. Not sure how one would go about that
LocalScripts are meant to be in StarterGui, StarterPlayerScripts, StarterCharacterScripts etc.
This won’t even work since parts only accept server sided script, you have to put it inside somewhere else this can work, also one thing is you’re also supposed to use :Connect() for MouseHover events
--inside ScreenGUI
local players = game:GetService("Players")
local uis = game:GetService("UserInputService")
local clickdetector = workspace.path_to_click
local hover = script.Hovering --boolvalue
local interact_txt = script.Parent.Interact --assuming its textlabel, set to script.Parent to disable GUI (script remains running if this is disabled
--detect keypress while hovering, fire event
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.E and hover.Value == true then
script.Parent.Pressed:FireServer()
end
end)
--set hover to true while hovering, make interact gui visible
clickdetector.MouseHoverEnter:Connect(function()
hover.Value = true --you have to assign value if they're a class object
interact_txt.Visible = true
end)
--set hover to false when leaving hover, make interact gui invisible
clickdetector.MouseHoverLeave:Connect(function()
hover.Value = false
interact_txt.Visible = false
end)
I see. If i were to make something similar to my current local script in starterplayer that fired the remote event of interactables, would that theoretically work? I’m trying to make the client trigger server events when they interact, so i’ve got to make the interact system hook up to the scripts inside the interactables
that works but for an interaction system like this, i’d put it on StarterGui since you’re updating the text label visibility in client (so none of the extra work are required by getting player gui, meaning that you just directly make variable and assign it to the screen gui)
Oh, i should’ve mentioned, i moved that code-snippet for the GUI visibility to my interactable highlighting script, and it works perfectly. I’m just trying to get the interaction event to trigger now. The visuals of it are functioning as-intended.
If the interaction manager thingy works, i’ll mark that as the solution. You’ll probably hear from me if it doesn’t work though.
For anyone that reviews this post: I made an interaction manager in StarterPlayer that, whenever you press E, checks if a part has an Interactable tag and if it does it fires an Interact remote event inside of the interactable. The interactable has a script inside of it that does the server-side of the interaction when it’s clicked.
I got a method that will work for you. Insert a module script on every interactable part.
Once the mouse moves, it will raycast to the new hit, where it would look for an interaction moduleScript, if it finds one it should require it.
The moduleScripts must have these 3 base functions:
.onFrame: Client calls this function every heartbeat .onHover: Fired when the hover starts .onKeyPress: fired when the user presses a key
Here’s an example of one of my moduleScripts for an interactable part:
local items = script.Parent.items
local cannon = script.Parent
local interaction = {}
local w_int = game.ReplicatedStorage.weapon_interactions
local dMouse = require(game.ReplicatedStorage.client_bindable.byMouse)
local rHex = "#DD3333"
local function fil2(n:number)
local split = tostring(math.round(n*10)/10):split(".")
split[2] = split[2] or "0"
return split[1].."."..string.sub(split[2], 1)
end
interaction.atHover = function()
local firstText = ""
if items.gunpowder.Value >= 1 then
if items.cannonball.Value >= 1 then
firstText = "Press F to fire the cannon!"
else
firstText = "This cannon is not equiped with a cannonball, insert one in!"
end
else
firstText = "The cannon is out of gunpowder, refill it!"
end
local pitch = math.round(-math.deg(select(3, cannon.cannon:GetPivot():ToOrientation()))*10)/10
local t =
{
firstText,
"Press Q or E to toggle cannon pitch.",
"Pitch: "..fil2(pitch).."°"
}
if cannon.inCooldown.Value then
table.insert(
t,
1,
'<font color="'..rHex..'">COOLDOWN! ('..fil2(cannon.inCooldown.secs.Value)..'s)</font>')
end
return t
end
local rnd = function(n, t)
return math.round(n / t) * t
end
interaction.triUpdate = function()
local firstText = ""
if items.gunpowder.Value >= 1 then
if items.cannonball.Value >= 1 then
firstText = "Press F to fire the cannon!"
else
firstText = "This cannon is not equiped with a cannonball, insert one in!"
end
else
firstText = "The cannon is out of gunpowder, refill it!"
end
local pitch = -math.deg(select(3, cannon.cannon:GetPivot():ToOrientation()))
local t =
{
firstText,
"Press Q or E to toggle cannon pitch.",
"Pitch: "..fil2(pitch).."°"
}
if cannon.inCooldown.Value then
table.insert(
t,
1,
'<font color="'..rHex..'">COOLDOWN! ('..fil2(cannon.inCooldown.secs.Value)..'s)</font>')
end
dMouse(t)
end
interaction.atkeypress = function(key:Enum.KeyCode)
if table.find({Enum.KeyCode.Q, Enum.KeyCode.E}, key) then
local mod = 1 if key == Enum.KeyCode.E then mod = -1 end
w_int.pitch_cannon:FireServer(cannon,7.5 * mod) return
end
if key == Enum.KeyCode.F then
w_int.fire_cannon:FireServer(cannon)
end
end
return interaction