You may have seen this post when searching for ways to play Gifs in Roblox.
However, this is limited to workspace parts. You are unable to use screen or billboard guis with this method (To my knowledge). I’ve made a function to solve that.
This function should compensate for Roblox’s 1024 x 1024 image size limit too.
This size limitation greatly decreases the quality of the final result. Other than using Roblox’s Pixelated Resample Mode, there isn’t a convenient way to fix this. (To my knowledge)
ImageLabel: ImageLabel Instance ImageWidth: Width in pixels of the spritesheet ImageHeight: Height in pixels of the spritesheet Rows: Number of rows on the spritesheet Columns: Number of columns on the spritesheet NumberOfFrames: Total number of frames or sections on the spritesheet (Optional) ImageId: Image Id after uploaded to Roblox (Optional) FPS: Frames per second to play
Function
local RobloxMaxImageSize = 1024
local function AnimateGif(ImageLabel:ImageLabel,ImageWidth,ImageHeight,Rows,Columns,NumberOfFrames,ImageId,FPS)
if ImageId then ImageLabel.Image = "http://www.roblox.com/asset/?id=" .. ImageId end
local RealWidth, RealHeight
if math.max(ImageWidth,ImageHeight) > RobloxMaxImageSize then -- Compensate roblox size
local Longest = ImageWidth > ImageHeight and "Width" or "Height"
if Longest == "Width" then
RealWidth = RobloxMaxImageSize
RealHeight = (RealWidth / ImageWidth) * ImageHeight
elseif Longest == "Height" then
RealHeight = RobloxMaxImageSize
RealWidth = (RealHeight / ImageHeight) * ImageWidth
end
else
RealWidth,RealHeight = ImageWidth,ImageHeight
end
local FrameSize = Vector2.new(RealWidth/Columns,RealHeight/Rows)
ImageLabel.ImageRectSize = FrameSize
local CurrentRow, CurrentColumn = 0,0
local Offsets = {}
for i = 1,NumberOfFrames do
local CurrentX = CurrentColumn * FrameSize.X
local CurrentY = CurrentRow * FrameSize.Y
table.insert(Offsets,Vector2.new(CurrentX,CurrentY))
CurrentColumn += 1
if CurrentColumn >= Columns then
CurrentColumn = 0
CurrentRow += 1
end
end
local TimeInterval = FPS and 1/FPS or 0.1
local Index = 0
task.spawn(function()
while task.wait(TimeInterval) and ImageLabel:IsDescendantOf(game) do
Index += 1
ImageLabel.ImageRectOffset = Offsets[Index]
if Index >= NumberOfFrames then
Index = 0
end
end
end)
end
Steps
Convert your gif to a spritesheet using any ‘gif to spritesheet’ converter that can be found online. I used this. There is an example of a spritesheet above.
Upload your spritesheet to roblox. A method to do this is shown below.
In the example above, I’ve copied the image id. We’ll need that id for later.
The next few steps varies on where your ImageLabel is located. But you need a script or local script to be able to access your ImageLabel. Use a script if your Gui is in the workspace, and use a local script if your Gui is a screen gui.
This is what I’m working with for this tutorial:
In your script, paste the function. It should look something like this:
Call the function and insert in your parameters. The description of each parameter is stated above. The image below is an example of calling it. (To make it more understandable, I’m using ‘parameter’ as a replacement of ‘arguments’. I understand that they are not the same thing.)
That should be it. Once your parameters are entered in, your gif should play correctly. There is an example .rbmx file above that you can refer to.
Hey, thanks for the tutorial. It’s really useful and informative. And this is definitely a good use of making gifs on Roblox instead of having multiple decals and rounding that up to play which is not very performant and takes a very long time!
11664 width, 144 height. You confused rows and colums.
Script calculate 12.64… and I replace it to 12
local FPSs = 81 / 3.4
local RobloxMaxImageSize = 1024
local function AnimateGif(ImageLabel:ImageLabel,ImageWidth,ImageHeight,Rows,Columns,NumberOfFrames,ImageId,FPS)
local NoFs = NumberOfFrames * 12
if ImageId then ImageLabel.Image = "http://www.roblox.com/asset/?id=" .. ImageId end
local RealWidth, RealHeight
if math.max(ImageWidth,ImageHeight) > RobloxMaxImageSize then -- Compensate roblox size
local Longest = ImageWidth > ImageHeight and "Width" or "Height"
if Longest == "Width" then
RealWidth = RobloxMaxImageSize
RealHeight = (RealWidth / ImageWidth) * ImageHeight
elseif Longest == "Height" then
RealHeight = RobloxMaxImageSize
RealWidth = (RealHeight / ImageHeight) * ImageWidth
end
else
RealWidth,RealHeight = ImageWidth,ImageHeight
end
local FrameSize = Vector2.new(RealWidth/Columns,RealHeight/Rows)
ImageLabel.ImageRectSize = Vector2.new(12,12)
local CurrentRow, CurrentColumn = 0,0
local Offsets = {}
for i = 1,NumberOfFrames do
local CurrentX = CurrentColumn * FrameSize.X
local CurrentY = CurrentRow * FrameSize.Y
table.insert(Offsets,Vector2.new(CurrentX,CurrentY))
CurrentColumn += 1
if CurrentColumn >= Columns then
CurrentColumn = 0
CurrentRow += 1
end
end
local TimeInterval = FPS and 1/FPS or 0.1
local Index = 0
task.spawn(function()
while task.wait(TimeInterval) and ImageLabel:IsDescendantOf(game) do
while true do
wait(TimeInterval)
Index += 12
ImageLabel.ImageRectOffset = Vector2.new(Index,0)
if Index >= NoFs then
ImageLabel.ImageRectOffset = Vector2.new(0,0)
Index = 0
end
end
end
end)
end
AnimateGif(script.Parent,11664,144,1,81,81,7985282257, FPSs)
A possible reason is because of roblox’s rounding error.
Each frame is only 5 pixels tall and a little larger than 5 pixels wide (After roblox’s limitations). Roblox might have rounded it down to 5 by 5 pixels, causing this to happen.
I suggest you use a 9 by 9 grid for the spritesheet instead of a 1 by 81, the quality would be better and this error should be fixed.
In your case, you have a very long spritesheet. This means that you have 1 very long row. Within your row, you have sections of your gifs, these are split up into columns.
I’m sorry if I seem petty, I didn’t mean it like that.
I did alter it a bit, but not too much. I mainly cleaned up the code, but should give the same result:
--[=[
The parent of all classes.
@class Sprite
]=]
local Sprite = { }
local RobloxMaxImageSize = 1024
--[=[
Animates the given sprite to play like a GIF.
@param image ImageLabel -- The image label that the sprite should be animated on
@param frameSize Vector2 -- The size of each individual frame
@param frames Vector2 -- The amount of frames on both the X and Y axis
@param fps number? -- The amount of frames per second that the sprite should be played at. Defaults to 30
@param imageId string? -- The image id that the image label should be set to, defaults to the initial image of the image label
]=]
function Sprite.Animate(image: ImageLabel, imageSize: Vector2, frames: Vector2, frameNumber: number, fps: number?, imageId: string?)
fps = fps or 30
imageId = imageId or image.Image
image:SetAttribute("IsAnimationActive", true)
if imageId then
image.Image = imageId
end
local RealWidth, RealHeight
local ImageWidth, ImageHeight = imageSize.X, imageSize.Y
if math.max(ImageWidth, ImageHeight) > RobloxMaxImageSize then -- Compensate roblox size
local Longest = ImageWidth > ImageHeight and "Width" or "Height"
if Longest == "Width" then
RealWidth = RobloxMaxImageSize
RealHeight = (RealWidth / ImageWidth) * ImageHeight
elseif Longest == "Height" then
RealHeight = RobloxMaxImageSize
RealWidth = (RealHeight / ImageHeight) * ImageWidth
end
else
RealWidth, RealHeight = ImageWidth, ImageHeight
end
local SingleFrameSize = Vector2.new(RealWidth/frames.Y, RealWidth/frames.X)
local TotalFrames = frameNumber
image.ImageRectSize = SingleFrameSize
local CurrentRow, CurrentColumn = 0, 0
local Offsets = { }
for _ = 1, TotalFrames do
local CurrentXPosition = CurrentColumn * SingleFrameSize.X
local CurrentYPosition = CurrentRow * SingleFrameSize.Y
table.insert(Offsets, Vector2.new(CurrentXPosition, CurrentYPosition))
CurrentColumn += 1
if CurrentColumn >= frames.Y then
CurrentColumn = 0
CurrentRow += 1
end
end
local SpritePlayTime = fps and 1/fps or 0.1
local CurrentIndex = 0
while image:IsDescendantOf(game) and image:GetAttribute("IsAnimationActive") do
task.wait(SpritePlayTime)
CurrentIndex += 1
image.ImageRectOffset = Offsets[CurrentIndex]
if CurrentIndex >= TotalFrames then
CurrentIndex = 0
end
end
end
--[=[
Stops the currently playing animation, if any.
@param image ImageLabel -- The image label that should stop being animated
]=]
function Sprite.StopAnimation(image: ImageLabel)
if image:GetAttribute("IsAnimationActive") then
image:SetAttribute("IsAnimationActive", false)
end
end
return Sprite