In my script, I have a system that attaches BodyForce instances to parts below the height of the water’s surface. This is done to replicate buoyancy. How can I improve my simulation?
Some issues I’ve noticed already are that the simulation seems to move too fast, and it slows down the server significantly when there are too many parts.
Here’s the FlashFlood script containing the buoyancy code:
local BaseDisaster = require(script.Parent.BaseDisaster)
local FlashFlood = BaseDisaster:Create()
FlashFlood.Name = "Flash Flood"
FlashFlood.Hint = "You'd better hope there's a high-up place around here!"
FlashFlood.Duration = 5
FlashFlood.PreparationTime = 10
FlashFlood.Finished = false
FlashFlood.BodyMovers = {}
function FlashFlood:Prepare()
FlashFlood.Finished = false
local waterPart = Instance.new("Part")
waterPart.Size = Vector3.new(400, 400, 400)
waterPart.CFrame = CFrame.new(0, -201, 0)
waterPart.Anchored = true
waterPart.CanCollide = false
waterPart.CastShadow = false
waterPart.BrickColor = BrickColor.new("Deep blue")
waterPart.Transparency = 0.5
waterPart.Reflectance = 1
waterPart.Material = Enum.Material.SmoothPlastic
waterPart.Parent = workspace.Disaster
local waterTexture = Instance.new("Texture")
waterTexture.Texture = "rbxassetid://14034336356"
waterTexture.Transparency = 0.5
waterTexture.Face = Enum.NormalId.Top
waterTexture.StudsPerTileU, waterTexture.StudsPerTileV = 12, 12
waterTexture.Parent = waterPart
self.WaterPart = waterPart
end
function FlashFlood:Start()
local waterPart = self.WaterPart
while waterPart.Position.Y < -176 do
waterPart.CFrame *= CFrame.new(0, 1 / 60, 0)
local waterTexture = waterPart.Texture
waterTexture.OffsetStudsU += 1 / 60
waterTexture.OffsetStudsV += 1 / 60
for _, v in workspace:GetChildren() do
if v:IsA("Model") then
local rootPart = v:FindFirstChild("Head")
if rootPart then
if rootPart.Position.Y < waterPart.Position.Y + 200 then
self:DamageCharacter(v, 0.5)
end
end
end
end
for _, v in workspace.Map:GetDescendants() do
if v:IsA("BasePart") then
if v.Anchored == false then
if v.Position.Y < waterPart.Position.Y + 200 then
local weld = v:FindFirstChildOfClass("WeldConstraint") or
v:FindFirstChildOfClass("Weld") or
v:FindFirstChildOfClass("Snap")
if weld then
weld:Destroy()
end
if not self.BodyMovers[v] then
local volume = v.Size.X * v.Size.Y * v.Size.Z
local waterDensity = 50
local gravity = workspace.Gravity
local force = volume * waterDensity * gravity
--[[local bodyVelocity = Instance.new("BodyVelocity")
bodyVelocity.Velocity = Vector3.new(0, 0.5, 0) * v.Mass
bodyVelocity.P = 1000
bodyVelocity.Parent = v
self.BodyMovers[v] = bodyVelocity]]
local bodyForce = Instance.new("BodyForce")
bodyForce.Force = Vector3.new(0, force / 60, 0)
bodyForce.Parent = v
self.BodyMovers[v] = bodyForce
end
else
if self.BodyMovers[v] then
self.BodyMovers[v]:Destroy()
self.BodyMovers[v] = nil
end
end
end
end
end
wait()
end
self.Finished = true
end
function FlashFlood:CleanUp()
for part, bodyMover in self.BodyMovers do
self.BodyMovers[part]:Destroy()
self.BodyMovers[part] = nil
part.AssemblyLinearVelocity = Vector3.zero
end
local waterPart = self.WaterPart
while waterPart.Position.Y > -200 do
waterPart.CFrame *= CFrame.new(0, -0.25, 0)
wait()
end
waterPart:Destroy()
self.WaterPart = nil
self:Reset()
end
return FlashFlood