Hello I’ve recently made a flag animation script that is very optimised and works with lots of Animated Flags.
It animates the flags locally when there are available players. It’s also scales with more flags performantly, it also works better than other flag animation scripts because its local, making the animation super smooth and it doesn’t produce unnecessary replication data.
I’d like to know that if there are any potential issues with this script and how I could make it better.
I would also like to know how to make this properly support StreamingEnabled and other replication related destroying stuff
Here is the server script
-- Flag model by Sinahi
-- Flag animation script by AsetCreator_ii(ALE111_boiPNG) - 2021 - Made a new script which is much better and much more performant.
--[[ReadMe*
This model uses MeshParts to animate the flag. The previous frame turns transparent
while the next frame becomes visible.
If you would like to use your own custom flag, for your ROBLOX group or country,
select all the children in the "Flag" model and paste in a ROBLOX decal asset in
the "TextureID" slot. If you receive an error, try subtracting 1 from the decal id.
rbxassetid://DECALID
http://www.roblox.com/asset/?id=DECALID
Any ROBLOX decal in the Developers Library will work, or you may upload your own
flag decal to insert in. Rectangular decals are recommended for this flag.
*If you use a decal with a transparent background in the MeshPart's TextureID,
the transparent background will default to black. Instead, insert the actual
decal into every MeshPart in "Flag." This will allow you to change the BrickColor
of the flag with the decal on top.
The flags have been UV mapped to flip the flag design on the other side.
e.g. You won't see the blue box of the United States flag on the other side
of the flag on its end, but close to the pole for both sides.
Thank you and have a wonderful day.
(MeshParts rendered using Blender)
--]]
-- // Configuration
local WAIT_TIME = 0.025 -- Time between each "Frame"
local FLAG_AMOUNT = 16 -- How many flags are there. Only change the value if you have changed the amount of flags inside the "Flag" model.
-- // Do not touch code below!!! Unless you known what you are doing. \/
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local StarterPlayerScripts = game:GetService("StarterPlayer"):WaitForChild("StarterPlayerScripts")
local flagModel = script.Parent:WaitForChild("Flag")
do
local foundAnimator = StarterPlayerScripts:FindFirstChild("FlagClientAnimator")
if not foundAnimator then
script:WaitForChild("FlagClientAnimator"):Clone().Parent = StarterPlayerScripts
end
local flagsContainer = ReplicatedStorage:FindFirstChild("FlagsContainer")
if not flagsContainer then
flagsContainer = Instance.new("Folder")
flagsContainer.Name, flagsContainer.Archivable, flagsContainer.Parent = "FlagsContainer", false, ReplicatedStorage
end
local flagInfo = Instance.new("Folder")
flagInfo.Name, flagInfo.Archivable = "FlagInfo", false
local waitTimeValue, flagAmountValue, flagObjectValue = Instance.new("NumberValue"), Instance.new("IntValue"), Instance.new("ObjectValue")
waitTimeValue.Name, flagAmountValue.Name, flagObjectValue.Name = "WaitTime", "FlagAmount", "FlagModel"
waitTimeValue.Value, flagAmountValue.Value, flagObjectValue.Value = WAIT_TIME, FLAG_AMOUNT, flagModel
waitTimeValue.Archivable, flagAmountValue.Archivable, flagObjectValue.Archivable = false, false, false
waitTimeValue.Parent, flagAmountValue.Parent, flagObjectValue.Parent = flagInfo, flagInfo, flagInfo
flagInfo.Parent = flagsContainer
end
task.wait(2)
if RunService:IsStudio() and #Players:GetPlayers() <= 0 then -- // We ideally want to do the animations on the client but if there are no clients we do it on the server.
local flags, last = {}, 1
for i = 1, FLAG_AMOUNT do
table.insert(flags, flagModel:WaitForChild(tostring(i)))
end
RunService.Heartbeat:Connect(function()
local current = math.clamp(math.floor((os.clock()) / WAIT_TIME) % FLAG_AMOUNT + 1, 1, FLAG_AMOUNT)
if current ~= last then
flags[current].Transparency = 0
flags[last].Transparency = 1
end
last = current
end)
end
Here is the client script
-- // Do not touch this script at all! Unless you known what you are doing. Also do not remove this as the flag will not work!
-- // Made by AsetCreator_ii(ALE111_boiPNG)
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local flagsContainer = ReplicatedStorage:WaitForChild("FlagsContainer")
local flagModelsHolder = {}
local function connectValue(object, callback, ...)
if object.Value then
callback(object.Value, ...)
end
while true do
object:GetPropertyChangedSignal("Value"):Wait()
if object.Value then
callback(object.Value, ...)
end
end
end
local function StartFlag(flag, waitTime, flagAmount)
local flags, flagTemp, last = {}, {}, 1
for i = 1, flagAmount do
table.insert(flagTemp, flag:WaitForChild(tostring(i)))
end
if not flagModelsHolder[flagAmount] then
flagModelsHolder[flagAmount] = {}
end
if not flagModelsHolder[flagAmount][waitTime] then
table.insert(flags, flagTemp)
flagModelsHolder[flagAmount][waitTime] = flags
else
table.insert(flagModelsHolder[flagAmount][waitTime], flagTemp)
return
end
task.wait(1)
RunService:BindToRenderStep("ClientFlagAnimation", 2048, function()
local current = math.clamp(math.floor(os.clock() / waitTime) % flagAmount + 1, 1, flagAmount)
if current ~= last then
for _, v in ipairs(flags) do
v[current].Transparency = 0
v[last].Transparency = 1
end
end
last = current
end)
end
Players.LocalPlayer.CharacterAdded:Wait()
task.wait(1)
print("Using AsetCreator_ii(ALE111_boiPNG)'s animated flag script.")
for _, v in ipairs(flagsContainer:GetChildren()) do
coroutine.wrap(connectValue)(v:WaitForChild("FlagModel"), StartFlag, v:WaitForChild("WaitTime").Value, v:WaitForChild("FlagAmount").Value)
end
flagsContainer.ChildAdded:Connect(function(child)
connectValue(child:WaitForChild("FlagModel"), StartFlag, child:WaitForChild("WaitTime").Value, child:WaitForChild("FlagAmount").Value)
end)
Here is a full game file.
Flag_Place1.rbxl (36.8 KB)
It doesn’t play nicely with StreamingEnabled and has other replication related issues (relating to flags being :Destroy()ed or otherwise cleaned up).