Script is SUPER unorganized and the image takes a while to load. Advice?

Ive noticed that this code could definetly be optimized better. Additionally, the image takes a while to spawn in. Any tips for what I can do or an alternative method of doing all this?

local plr = game.Players.LocalPlayer


local plrs = game:GetService("Players")
local plrList = plrs:GetPlayers()




local msgRunning = false



local ImageLabel = script.Parent.Parent.SpeakerImage

local ScreenGui = script.Parent.Parent

local getImgFunctionDoneRunning = false

local function getImg()
	
	getImgFunctionDoneRunning = false
	
	local randomizedPlr = math.random(1, #plrList)
	local chosenSpeakerId = plrList[randomizedPlr].UserId
	
	
	
	local processedImage = plrs:GetUserThumbnailAsync(chosenSpeakerId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
	
	--ImageLabel.Image = processedImage


	getImgFunctionDoneRunning = true
	return processedImage
	
end

local function typeMsg(input, intervalSpeed, isSpeakerAPlayer)
	
	local LoadedPlayerImg = getImg()
	local CounselorImg = plrs:GetUserThumbnailAsync(0, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
	
	
	
	repeat
		task.wait()
	until getImgFunctionDoneRunning == true
	
	if isSpeakerAPlayer == true then
		

		msgRunning = true
		for i = 1, #input do
			task.wait(intervalSpeed)
			local substring = string.sub(input, 1, i)

			script.Parent.Text = substring

			if i >= #input then task.wait(2) msgRunning = false end
		end
		
	else
		ImageLabel.Image = CounselorImg

		msgRunning = true
		for i = 1, #input do
			task.wait(intervalSpeed)
			local substring = string.sub(input, 1, i)

			script.Parent.Text = substring

			if i >= #input then task.wait(2) msgRunning = false end
		end
	end
	
	
	
	
	
	

	
	
end



--Scene One
ScreenGui.Enabled = false
task.wait(5)
ScreenGui.Enabled = true
local msg1 = "Hello there! I am a test NPC for this game."
typeMsg(msg1 .. " You must be "..plr.Name, 0.05, false)


repeat 
	task.wait()
	
until msgRunning == false

local msg2 = "I have to go for now. Have a good one, and explore a bit!"
typeMsg(msg2, 0.05, false)





ScreenGui.Enabled = false

task.wait(2)

ScreenGui.Enabled = true

local msg3 = "Hey does anyone wanna tell some stories around the fire?"
typeMsg(msg3, 0.05, true)

1 Like

there’s your problem

also please format, its not hard its hurting my eyes and im sure its hurting yours too. do yourself a favor (i mean if you want to idk)

Try something like this

local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local ScreenGui = script.Parent.Parent
local ImageLabel = ScreenGui:FindFirstChild("SpeakerImage")
local TextLabel = script.Parent

local msgRunning = false

-- Utility to get player headshot
local function getPlayerHeadshot(userId)
	return Players:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
end

-- Typing message effect
local function typeMessage(message, interval, isSpeakerPlayer)
	msgRunning = true

	-- Set speaker image
	if isSpeakerPlayer then
		local playerList = Players:GetPlayers()
		if #playerList > 0 then
			local randomPlayer = playerList[math.random(1, #playerList)]
			ImageLabel.Image = getPlayerHeadshot(randomPlayer.UserId)
		end
	else
		ImageLabel.Image = getPlayerHeadshot(0) -- default Roblox counselor image
	end

	-- Typewriter effect
	for i = 1, #message do
		TextLabel.Text = string.sub(message, 1, i)
		task.wait(interval)
	end

	task.wait(2)
	msgRunning = false
end

-- MAIN DIALOG FLOW
ScreenGui.Enabled = false
task.wait(5)
ScreenGui.Enabled = true

typeMessage("Hello there! I am a test NPC for this game. You must be " .. localPlayer.Name, 0.05, false)

repeat task.wait() until not msgRunning

typeMessage("I have to go for now. Have a good one, and explore a bit!", 0.05, false)

ScreenGui.Enabled = false
task.wait(2)
ScreenGui.Enabled = true

typeMessage("Hey does anyone wanna tell some stories around the fire?", 0.05, true)

Try this:

local plr = game.Players.LocalPlayer
local plrs = game:GetService("Players")
local ScreenGui = script.Parent.Parent
local ImageLabel = ScreenGui.SpeakerImage

local msgRunning = false
local loadedImages = {}  -- Table to store the images once loaded

-- Function to pre-load the player's image in parallel
local function loadPlayerImageAsync(userId)
    -- This coroutine will load the image asynchronously
    local promise = coroutine.create(function()
        local image = plrs:GetUserThumbnailAsync(userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size420x420)
        loadedImages[userId] = image  -- Store the image once it's loaded
    end)
    coroutine.resume(promise)
end

-- Function to type the message
local function typeMsg(input, intervalSpeed, isSpeakerAPlayer)
    -- Determine the speaker and load the image in parallel
    local speakerImage

    -- Preload speaker image asynchronously
    local randomizedPlr = plrs:GetPlayers()[math.random(1, #plrs:GetPlayers())]  -- Random player selection
    if isSpeakerAPlayer then
        loadPlayerImageAsync(randomizedPlr.UserId)
        speakerImage = nil  -- Placeholder, will be updated once loaded
    else
        loadPlayerImageAsync(0)  -- NPC or default image for counselor
        speakerImage = nil  -- Placeholder, will be updated once loaded
    end

    -- Start typing the message
    msgRunning = true
    local currentText = ""

    for i = 1, #input do
        task.wait(intervalSpeed)
        currentText = string.sub(input, 1, i)
        script.Parent.Text = currentText
    end

    -- Wait for the image to be loaded if not already
    while speakerImage == nil do
        if loadedImages[randomizedPlr.UserId] then
            speakerImage = loadedImages[randomizedPlr.UserId]
        elseif loadedImages[0] then
            speakerImage = loadedImages[0]
        end
        task.wait(0.1)  -- Check every 100ms for the image
    end

    -- Set the image once it's loaded
    ImageLabel.Image = speakerImage

    -- End of message
    task.wait(2)  -- Wait 2 seconds before completing
    msgRunning = false
end

-- Scene One
ScreenGui.Enabled = false
task.wait(5)
ScreenGui.Enabled = true

local msg1 = "Hello there! I am a test NPC for this game."
typeMsg(msg1 .. " You must be " .. plr.Name, 0.05, false)

-- Wait for the message to finish
repeat
    task.wait()
until not msgRunning

local msg2 = "I have to go for now. Have a good one, and explore a bit!"
typeMsg(msg2, 0.05, false)

ScreenGui.Enabled = false
task.wait(2)
ScreenGui.Enabled = true

local msg3 = "Hey, does anyone wanna tell some stories around the fire?"
typeMsg(msg3, 0.05, true)