I’ve made a small script that essentially checks if a players character Y position is lower than -50 and it will transport them back to the last safe position. I did this just to mess around with Bézier Curves and I’d really appreciate if I could get some tips with things like formatting my code and making it more efficient! I wont really be using this for anything so I thought it was perfect for asking for critiques.
local character = script.Parent
local plr = game.Players:GetPlayerFromCharacter(character)
local bubble = script.Bubble
local weld = script.Bubble.HRPWeld
local BubbleInflateHeight = -50
local BubbleHeightOffset = 80
local LastSafePos
bubble.Parent = script.Parent.HumanoidRootPart
weld.Part1 = script.Parent.HumanoidRootPart
-- Quadratic Beizer to calculate curve of the path for the bubble
local function FindPointOnBeizer(t,p0,p1,p2)
return (1-t)^2*p0+2*(1-t)*t*p1+t^2*p2
end
-- Checks for HumanoidRootPart before running every 0.3 seconds to avoid
-- errors when the player dies
while wait(0.3) and character:FindFirstChild("HumanoidRootPart") do
local RayParams = RaycastParams.new()
-- Filter out Parts inside the character as the bubble would end up dropping you in the void
local charparts = {}
for i,v in pairs(character:GetDescendants()) do
if v:IsA("Part") or v:IsA("UnionOperation") or v:IsA("MeshPart") then
table.insert(charparts,#charparts+1,v)
end
end
RayParams.FilterDescendantsInstances = charparts
RayParams.FilterType = Enum.RaycastFilterType.Blacklist
local ResultRaycast = workspace:Raycast(character.HumanoidRootPart.Position,-(character.HumanoidRootPart.CFrame.UpVector*10),RayParams)
if ResultRaycast and ResultRaycast.Instance.CanCollide == true then
LastSafePos = ResultRaycast.Position + Vector3.new(0,8,0)
end
if character.HumanoidRootPart.Position.Y <= BubbleInflateHeight
and LastSafePos ~= nil and character.Humanoid.Health ~= 0 then
character.HumanoidRootPart.Anchored = true
bubble.Transparency = 0.6
bubble.Bubble.Transparency = 0
bubble.Inflate:Play()
bubble.Moving:Play()
local Anims = script.Anims:GetChildren()
local Anim = Anims[math.random(1,#Anims)]
local Animation = character.Humanoid:LoadAnimation(Anim)
Animation:Play()
local StartPoint = character.HumanoidRootPart.Position
local Midpoint = Vector3.new(
character.HumanoidRootPart.Position.X,
LastSafePos.Y+BubbleHeightOffset,
character.HumanoidRootPart.Position.Z)
for count = 0,1.01,0.01 do
wait(0.01)
if character.HumanoidRootPart then
local pos = FindPointOnBeizer(count,StartPoint,Midpoint,LastSafePos)
--Uses CFrame rather than Position due to problems replicating from client to server
local LookAt = character.HumanoidRootPart.CFrame * CFrame.new(Vector3.new(0,0,-2))
character.HumanoidRootPart.CFrame = CFrame.lookAt(pos,LookAt.Position)
character.HumanoidRootPart.Orientation = Vector3.new(0,character.HumanoidRootPart.Orientation.Y,0)
end
end
if character:FindFirstChild("HumanoidRootPart") and character.HumanoidRootPart:FindFirstChild("Bubble")
and bubble:FindFirstChild("Bubble") then
character.HumanoidRootPart.Position = LastSafePos
Animation:Stop()
bubble.Moving:Stop()
bubble.Pop:Play()
bubble.Transparency = 1
bubble.Bubble.Transparency = 1
-- Set all character part's velocity to 0 to prevent flinging/ragdoll
for i,v in pairs(character:GetDescendants()) do
if v:IsA("Part") or v:IsA("UnionOperation") or v:IsA("MeshPart") then
v.Velocity = Vector3.new(0,0,0)
end
end
character.HumanoidRootPart.Anchored = false
else
plr:LoadCharacter()
end
end
end
Example of what this code does: