I’m looking to create a player launchpad that doesn’t suffer from the delays inherent to .Touched. I’ve seen that apparently Magnitude can be used for this, but I’m having trouble figuring out exactly how I can use magnitude to detect the presence of a player.
What kind of logic do I need to use magnitude to detect a player that is touching a launchpad?
So what you can do alternatively to .Touched is iterate through the workspace, going through each and every character in the game, while finding the magnitude from the player to the launchpad. (CharactersPrimaryPartsPos - LaunchPadPos).magnitude. Then if a player is within a certain magnitude of the launchpad, you can run the function that launches the player.
Have you considered using the .Touched event on the client, then firing a function to the server? There aren’t really many other ways to use magnitude other than repeatedly looping through the players in the game. You can even do a sanity check on the server to make sure that the clients request is reasonable.
(I agree using magnitude in the manner I explained can be slow)
That’s a clever idea - put a local script in the client that detects when a booster is touched, have it fire an event that the server listens for, and use that to bounce the player. I’ll have to give that a try and see if it works better.
So I’m trying to make this work, but I’m running into a strange problem. The bouncer is going to pass two pieces of data: the player’s name, and the bouncer’s orientation to the server script so that it knows which direction to bounce the player. The problem is that when I pass this data, I get two instances of the player instead of one instance of the player and a number.
The code, for reference:
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local bounceEvent = ReplicatedStorage:WaitForChild("bounceEvent")
local player = game.Players.LocalPlayer
local character = player.Character
if not character or not character.Parent then
character = player.CharacterAdded:wait()
end
local humanoid = character:WaitForChild("Humanoid")
local cooldown = .2
local isTouched = false
humanoid.Touched:connect(function(hit)
if not isTouched then
if hit.Name == "bouncer" then
isTouched = true
local direction = hit.Orientation.Y
bounceEvent:FireServer(player, direction)
print("local side " .. direction .. " bouncer fired by " .. character.Name)
wait(cooldown)
isTouched = false
end
else
end
end)
Server script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local bounceEvent = Instance.new("RemoteEvent", ReplicatedStorage)
bounceEvent.Name = "bounceEvent"
local function onBounceFired(player, direction)
print(player)
print(direction)
end
bounceEvent.OnServerEvent:Connect(onBounceFired)
The result I’m expecting from the server script is:
ObsidianRook
0
But I’m getting
ObsidianRook
ObsidianRook
Why is this happening? How else could I pass these two bits of data?
The player is automatically passed as an argument from the client to the server, you don’t need to pass the player again. Just do :FireServer(direction)
The LocalScript needs to be in the player, so it can’t watch for a launchpad to be touched. Also, if Humanoid couldn’t be touched I wouldn’t be getting anything back, right?
Alrighty, so I just tested the scripts, as well as the humanoid touched event (super cool)
and everything works as is supposed to?
Client:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local bounceEvent = ReplicatedStorage:WaitForChild("bounceEvent")
local player = game.Players.LocalPlayer
local character = player.Character
local humanoid = character:WaitForChild("Humanoid")
local cooldown = .2
local isTouched = false
humanoid.Touched:connect(function(hit)
if not isTouched then
if hit.Name == "bouncer" then
isTouched = true
local direction = hit.Orientation.Y
bounceEvent:FireServer(direction)
print("local side " .. direction .. " bouncer fired by " .. character.Name)
wait(cooldown)
isTouched = false
end
else
end
end)
Server:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local bounceEvent = ReplicatedStorage:WaitForChild("bounceEvent")
bounceEvent.Name = "bounceEvent"
local function onBounceFired(player, direction)
print(player)
print(direction)
end
bounceEvent.OnServerEvent:Connect(onBounceFired)
Really the only change I made was the FireServer one, and instead of instancing a remote event, I added it to the replicated storage beforehand. (Shouldn’t really matter)
The output is:
local side 2.039999961853 bouncer fired by TheAnimeDev28 - Client - LocalScript:15
12:29:30.292 TheAnimeDev28 - Server - Script:8
12:29:30.292 2.039999961853 - Server - Script:10
I’m so glad that worked! Does everything else work properly? (You can just like this post if everything does work and if I answered your question fully, mark a solution).
All I need to figure out now is how to figure out how to actually make the player bounce how I want. In the old bounce pad, I used a BodyForce with hardcoded values, but since this script will have to work on all bounce pads, I need to figure out some way to mathematically generate a Vector3 - or rather, the X and Z values of one - based on the orientation value passed into the function. I have no idea how I’m going to do that yet.
I’m sure you can find other forum posts on things similar to this, but it seems that your original question was answered which is great . Just keep practicing and improving!