I am currently in development of a pirate ship-related game. The player can use WASD to drive the ship but also I’m looking to add a way to use Q&E to fire the left and right cannons on the ship. I created a local script attempting user input service to fire a Bindable Event towards the cannons. My script currently doesn’t even pick up the buttons being pressed in the first place. I tried local and regular scripts. Similar to how a police car drives and you are able to toggle certain things like sirens, horn or headlights, I attempted to copy some code and modify it to this but it never worked either. This is my current Progress:
local CannonQ = script.Parent.Parent.CanQ
local CannonE = script.Parent.Parent.CanE
local UserInputService = game:GetService(“UserInputService”)
UserInputService.InputBegan:Connect(function(key)
if key.KeyCode == Enum.KeyCode.Q then
print(“fireQ2”)
CannonQ:Fire()
end
end)
UserInputService.InputBegan:Connect(function(key)
print(“fireE1”)
if key.KeyCode == Enum.KeyCode.E then
print(“fireE2”)
CannonE:Fire()
end
end)
Is this a problem with the replication or a problem with the mechanic overall?
Thanks to FilteringEnabled, if you want anything to replicate from the client (user input) to the server (other players seeing it), you’ll have to use remote events rather than bindable events so the information is sent over to the server for all other clients to receive.
The above problem may be separate from your current problem, though; according to your post, you can’t even get the button presses to register, and that’s definitely a local script error. The main potential problem I see is addressing the first two variables. When in a local script, sometimes instances won’t load in before scripts are ran, so it may help to use :WaitForChild() on those instances rather than directly referring to them.
LocalScripts won’t run code unless it is a descendant of
A Player’s Backpack, such as a child of a Tool
A Player’s character model
A Player’s PlayerGui
A Player’s PlayerScripts.
The ReplicatedFirst service
you can find more information on LocalScripts here
What I personally would do is, in a local script under StarterPlayerScripts detect if the Player is sitting in the pirate ship and then begin getting input if they are. If they arent, disconnect the functions.
The Button detection is stored on the ship itself and nothing happens locally scripting wise. There is nothing in the output either after the change done(adding wait for child on variables, and changing it to a regular script). If there is no way for the server to track the buttons being pressed by the player, is the only way a local script on the player firing to the ship if the player is on the ship?
Or would a [Server->Client-> Server] model work, where if a player sits in the ship, the server fires and creates a local script in the players scripts, and thus begins tracking the player key presses until the player jumps out of the seat destroying the script.
Both of those ideas would work, but it’d be easier to go with the first method. Also, as @SkoobiDoobiDoo mentioned, your local script cannot run unless it’s parented correctly, which is something I initially overlooked.
You could parent the local script to StarterPlayerScripts, then connect it to a remote event created in a fitting place such as ReplicatedStorage for the button detection. When the button is pressed, use :FireServer() to send the signal to a server script inside of the ship which will operate the vehicle functions. You also want to check to make sure the player who pressed the button is the same as the player on the seat. Remote events automatically pass the player as an argument to the server, so you can do something like this on the server script:
local remote = game.ReplicatedStorage.ShipRemote
local seat = script.Parent
local CannonQ = seat.Parent.CanQ
local CannonE = seat.Parent.CanE
remote.OnServerEvent:Connect(function(player,button)
local chara = player.Character
if chara then
local human = chara:FindFirstChildWhichIsA("Humanoid")
if human and human == seat.Occupant then --check mentioned above
if button == "Q" then
--code to shoot CannonQ
elseif button == "E" then
--code to shoot CannonE
end
end
end
end)
You can then handle the user input on the client in a local script, likely in StarterPlayerScripts:
local remote = game.ReplicatedStorage:WaitForChild("ShipRemote")
local UserInputService = game:GetService("UserInputService")
UserInputService.InputBegan:Connect(function(key)
if key.KeyCode == Enum.KeyCode.Q then
remote:FireServer("Q")
elseif key.KeyCode == Enum.KeyCode.E then
remote:FireServer("E")
end
end)
I don’t know how familiar you are with remote events/functions, but whenever firing from client to server, don’t let the arguments confuse you. The only argument passed in the local script is a string value, either “Q” or “E”, to indicate which key was pressed. However, in the server script, you can see that the function has two arguments, the first being the player. This personally confused me a lot when I first learned about remotes, so just remember that the ‘player’ is always automatically there as the first argument when the client uses :FireServer(), even though it isn’t passed as an argument.