I’m making a game where you have to push people off a map. I got started on my round system, but the push mechanic becomes super buggy on the map.
Here is a video demonstrating the bug:
Here is my push script:
local Debris = game:GetService("Debris")
local tool = script.Parent
local RANGE = 3
local WIDTH, HEIGHT = 6, 4
local DELTA_V = 120
local RAGDOLL_TIME = 2
local remote = tool:WaitForChild("PushEvent")
local function ragdoll(character)
local humanoid = character:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid:ChangeState(Enum.HumanoidStateType.Physics)
end
local motors = {}
for _, joint in pairs(character:GetDescendants()) do
if joint:IsA("Motor6D") then
table.insert(motors, {Motor=joint, Parent=joint.Parent, C0=joint.C0, C1=joint.C1})
local socket = Instance.new("BallSocketConstraint")
local a1 = Instance.new("Attachment")
local a2 = Instance.new("Attachment")
a1.Parent = joint.Part0
a2.Parent = joint.Part1
socket.Parent = joint.Parent
socket.Attachment0 = a1
socket.Attachment1 = a2
a1.CFrame = joint.C0
a2.CFrame = joint.C1
socket.LimitsEnabled = true
socket.TwistLimitsEnabled = true
joint:Destroy()
end
end
return motors
end
local function standUp(character, motors)
local humanoid = character:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.PlatformStand = false
end
for _, data in ipairs(motors) do
if data.Parent and character.Parent then
local newMotor = Instance.new("Motor6D")
newMotor.Part0 = data.Motor.Part0
newMotor.Part1 = data.Motor.Part1
newMotor.C0 = data.C0
newMotor.C1 = data.C1
newMotor.Parent = data.Parent
end
end
end
local function push(character)
local hrp = character:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local size = Vector3.new(WIDTH, HEIGHT, RANGE)
local cf = hrp.CFrame * CFrame.new(0, 0, -(RANGE/2 + 2))
local partsInBox = workspace:GetPartBoundsInBox(cf, size)
local alreadyHit = {}
local hitboxVisual = Instance.new("Part")
hitboxVisual.Size = size
hitboxVisual.CFrame = cf
hitboxVisual.Anchored = true
hitboxVisual.CanCollide = false
hitboxVisual.CanQuery = false
hitboxVisual.CanTouch = false
hitboxVisual.Transparency = 0.5
hitboxVisual.Color = Color3.fromRGB(255, 0, 0)
hitboxVisual.Parent = workspace
Debris:AddItem(hitboxVisual, 0.15)
for _, part in ipairs(partsInBox) do
local otherChar = part:FindFirstAncestorOfClass("Model")
local hum = otherChar and otherChar:FindFirstChildOfClass("Humanoid")
local otherHRP = otherChar and otherChar:FindFirstChild("HumanoidRootPart")
if not (hum and otherHRP) then continue end
if otherChar == character then continue end
if alreadyHit[otherChar] then continue end
alreadyHit[otherChar] = true
local targetChar = otherChar
local targetHRP = otherHRP
local myHRP = hrp
task.spawn(function()
if not (targetChar and targetHRP and myHRP) then return end
local motors = ragdoll(targetChar)
task.wait(0.05)
local originalOwner = targetHRP:GetNetworkOwner()
local dir = targetHRP.Position - myHRP.Position
dir = Vector3.new(dir.X, 5, dir.Z)
if dir.Magnitude > 0 then
dir = dir.Unit
local impulse = dir * targetHRP.AssemblyMass * DELTA_V
targetHRP:SetNetworkOwner(nil)
task.wait()
if targetHRP.ApplyImpulse then
targetHRP:ApplyImpulse(impulse)
else
targetHRP.AssemblyLinearVelocity += impulse / targetHRP.AssemblyMass
end
end
task.wait(RAGDOLL_TIME)
if targetChar.Parent then
standUp(targetChar, motors)
if originalOwner then
targetHRP:SetNetworkOwner(originalOwner)
end
end
end)
end
end
remote.OnServerEvent:Connect(function(player)
local char = player.Character
if char then
push(char)
end
end)
Here is my round system:
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local allMaps = {"Snowy Isles", "Lava Lane", "Grassy Hills", "Desert Dunes"}
local mapImages = {["Snowy Isles"]=75025886098830, ["Lava Lane"]=140550269282963, ["Grassy Hills"]=84750033257545, ["Desert Dunes"]=101262479079545}
local padsModel = workspace:WaitForChild("VotingPads")
local pads = {padsModel:WaitForChild("VotingPad1"), padsModel:WaitForChild("VotingPad2"), padsModel:WaitForChild("VotingPad3")}
local labelsModel = workspace:WaitForChild("Labels")
local labels = {labelsModel:WaitForChild("Label1"), labelsModel:WaitForChild("Label2"), labelsModel:WaitForChild("Label3")}
local imageholdersModel = workspace:WaitForChild("ImageHolders")
local imageHolders = {imageholdersModel:WaitForChild("ImageHolder1"), imageholdersModel:WaitForChild("ImageHolder2"), imageholdersModel:WaitForChild("ImageHolder3")}
local spawns = workspace:WaitForChild("Spawns")
local lobbySpawn = workspace:WaitForChild("LobbySpawn")
local currentMaps = {}
local votes = {}
local alivePlayers = {}
local function shuffle(tbl)
local t = {table.unpack(tbl)}
for i = #t,2,-1 do
local j = math.random(i)
t[i],t[j]=t[j],t[i]
end
return t
end
local function pickMaps()
local shuffled = shuffle(allMaps)
currentMaps = {shuffled[1],shuffled[2],shuffled[3]}
votes = {}
for i,label in ipairs(labels) do
local gui = label:WaitForChild("SurfaceGui")
if gui and gui:FindFirstChild("TextLabel") then
gui.TextLabel.Text = currentMaps[i]
end
end
for i,image in ipairs(imageHolders) do
local gui = image:FindFirstChild("SurfaceGui")
if gui then
local frame = gui:FindFirstChild("Frame")
if frame then
local img = frame:FindFirstChild("ImageLabel")
if img then
img.Image = "rbxassetid://"..mapImages[currentMaps[i]]
end
end
end
end
end
local function updateVotes()
local counts = {0,0,0}
for _,padIndex in pairs(votes) do counts[padIndex]+=1 end
for i,pad in ipairs(pads) do
local gui = pad:FindFirstChild("BillboardGui")
if gui and gui:FindFirstChild("TextLabel") then
gui.TextLabel.Text = currentMaps[i].." - Votes: "..counts[i]
end
end
end
local function onPadTouched(padIndex, hit)
local plr = Players:GetPlayerFromCharacter(hit.Parent)
if plr and votes[plr] ~= padIndex then
votes[plr] = padIndex
updateVotes()
end
end
for i,pad in ipairs(pads) do
pad.Touched:Connect(function(hit) onPadTouched(i,hit) end)
end
Players.PlayerRemoving:Connect(function(plr)
votes[plr]=nil
updateVotes()
end)
local function getWinningMap()
local counts = {0,0,0}
for _,idx in pairs(votes) do counts[idx]+=1 end
local maxVotes = math.max(unpack(counts))
local winners = {}
for i,v in ipairs(counts) do if v==maxVotes then table.insert(winners,i) end end
return currentMaps[winners[math.random(1,#winners)]]
end
local function teleportPlayer(plr)
local spawnList = spawns:GetChildren()
local randSpawn = spawnList[math.random(1,#spawnList)]
local char = plr.Character
if char and char:FindFirstChild("HumanoidRootPart") then
char.HumanoidRootPart.Position = randSpawn.Position + Vector3.new(0,3,0)
end
end
local function endRound(winnerMapName)
local winner
if #alivePlayers==1 then winner=alivePlayers[1] end
if winner then
print("Winner: "..winner.Name)
end
for _,plr in ipairs(Players:GetPlayers()) do
if plr.Character and plr.Character:FindFirstChild("HumanoidRootPart") then
plr.Character.HumanoidRootPart.Position = lobbySpawn.Position + Vector3.new(0,5,0)
end
end
local map = workspace:FindFirstChild(winnerMapName)
if map then
map.Parent = ReplicatedStorage.Maps
end
pickMaps()
task.delay(15,function()
local winnerMap=getWinningMap()
print("Winning Map: "..winnerMap)
startRound(winnerMap)
end)
end
function startRound(winnerMapName)
local pickedMap = ReplicatedStorage.Maps:FindFirstChild(winnerMapName)
if pickedMap then pickedMap.Parent=workspace end
alivePlayers = {}
for _,plr in pairs(Players:GetPlayers()) do
teleportPlayer(plr)
table.insert(alivePlayers,plr)
local char = plr.Character
if char then
local hrp = char:FindFirstChild("HumanoidRootPart")
if hrp then
hrp.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
end
local humanoid = char:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.Died:Connect(function()
local idx = table.find(alivePlayers,plr)
if idx then table.remove(alivePlayers,idx) end
if #alivePlayers<=1 then endRound(winnerMapName) end
end)
end
end
end
end
pickMaps()
task.delay(15,function()
local winnerMap=getWinningMap()
print("Winning Map: "..winnerMap)
startRound(winnerMap)
end)
I’ve tried moving the maps from replicatedstorage to serverstorage and I’ve tried keeping the maps in workspace and changing cancollide and transparency properties accordingly.