How to check a value changed more efficiently

Hello, I am making a round system and I am currently using a while wait(1) do loop to check a script value.

I was thinking it MIGHT start getting laggy so I came here for some tips.

Here is my script:

local module = require(script.FetchRoundSystem)

local intermission = true

while wait(1) do
    if intermission then
        module.getCurrentRound("Intermission", 5, 0, 1)
        intermission = not intermission
    else
        module.getCurrentRound("Game in progress", 5, 0, 1)
        intermission = not intermission
    end
end

If there is no way I am fine with keeping it the way it is.

Thanks :slightly_smiling_face:

1 Like

Is it not possible for you to use a BoolValue for the intermission value rather than using a wait or does it have to be a variable boolean?

I would prefer it to be a variable boolean.

Have you even tested the script before posting? It’s just setting intermission value back in forth from false and true every second.

Um what?

I have tested it, it doesn’t keep changing the value it waits for the module function to end then changes it. I used print statements to come to this conclusion.

You can keep the variable. An alternative is listening for changes of NumberValue, but that requires the use of connections, so it’s a good question what is more performance friendly. I’d say you should keep it as it currently is.

local module = require(script.FetchRoundSystem)

local intermission = true -- variable inside script

--[[
	Checking every second (perhaps 1.5 or 2 seconds) is not performance demanding.
	A questionable alternative is listening for changes in external value using
	BoolValue:GetPropertyChangedSignal("Value"):Connect(function() end).
	
	Would that make a perforamnce difference?
	I don't think so. It would probably worsen the situation.

	Your script is fine.
]]

while wait(1) do
	if intermission then
		-- We currently don't know how long this function runs.
		module.getCurrentRound("Intermission", 5, 0, 1)
		intermission = false
	else
		module.getCurrentRound("Game in progress", 5, 0, 1)
		intermission = not intermission -- Why constant changing to true?
	end
end

EDIT
I understand why you are using not, I use it too from time to time, depending on the example. I was talking about constant changing of intermission value, which doesn’t make sense at first sight, unless you know how the module works.

As for connections, they are useful, but you can avoid them in this case, because they are not necessary and perhaps take up more memory.

EDIT (2)

@GamingExpert0312 I would stick to while-loop if I were you, because it’s not running rapidly and/or doing any serious calculations. Connections are just an alternative for more demanding scripts, but consume some memory themselves, so while-loops are most likely the right choice in this case.

Don’t worry, this won’t cause any lag. Even if you ran this script 30 times a second the lag maybe wouldn’t be even noticable. Servers are very capable. The point is to optimize scripts when you can and what you’ve shown us is pretty efficient (running only once per second).

I was thinking of using :GetPropertyChangedSignal, I will use that if you think it is better.

Also I use

intermission = not intermission

because I just like doing that.

If that’s the case then have you tried calling the next function at the end of the functions? If they run to completion then make the next one fire at the end of the function.

Since you said the loop waits till the function is done, then it can be kept like this since there’s no unnecessary checking for the variable. I think your code can be kept like this. Although one thing I would do is put intermission = not intermission outside of the if statement at the end since it’s being used in both conditions anyways

1 Like

Hey I did what you said, so um right now it only runs when the value is actually changed.

local module = require(script.FetchRoundSystem)

local isIntermission = script.Parent.IsIntermission

isIntermission:GetPropertyChangedSignal("Value"):Connect(function()
	if isIntermission.Value then
		module.getCurrentRound("Intermission", 3, 0, 1)
		isIntermission.Value = false
	else
		module.getCurrentRound("Game in progress", 3, 0, 1)
		isIntermission.Value = true
	end
end)

This may seems a bit stupid, but how would I make it run anyway?

I need this constantly running so I will just stick to a while loop. Thank you for the help though.

So I run this function IN a while loop or?

Maybe something like this works? Wrote this by head so it might have some mistakes, but you get the idea.

local module = require(script.FetchRoundSystem)

local intermission = true

local function updateIntermission()
    module.getCurrentRound(intermission and "Intermission" or "Game in progress", 5, 0, 1) -- Using a ternary operator to switch between the two messages, could use an if statement too but this is more compact.

    intermission = not intermission

    updateIntermission() -- Repeat
end

updateIntermission() -- Run this in a coroutine if you don't want the script's thread to yield
1 Like

Use Value.Changed:Connect(function() - it fires when a value changes (although you might have already worked that out)

I prefer to use the :GetPropertyChangedSignal() for some reason.

Hi, just noting some quick things about your code to help you.

You are not really polling in your current code, it’s more kind of waiting. Your code would be equivalent to:

while true do
  wait(1)
  module.getcurrentround(intermission...)
  wait(1)
  module.getcurrentround(gameinprogres...)
end

That is because waiting for the next round is not determined by your polling your boolean, but by waiting for the module’s function to return.

Incidentally, if you have an if/else statement, and an identical line of code on the end of both, it is easy to factor that duplicated line out: DRY.

So your current approach is not inefficient, because you are not really ‘polling’, and the while loop is simply your main game loop. In general, it is indeed good to avoid polling, and usually dealing with incoming signals right away is usually the way to go - rather than storing the result in some variable and polling for it.

Indeed, firing a RBXScriptSignal | Documentation - Roblox Creator Hub and listening to that is a better solution than polling, but sometimes a simple function call is enough too.

But all that kind of logic is only to find out when the next task is ready to start, and because your module’s functions return when they are done, none of that is needed in this case!

Hope this helped your understanding!

Edit: oops, didn’t notice before that @EmbatTheHybrid also already said this :slight_smile:

1 Like

Haha, it’s okay, sometimes we skim through replies and not notice what we said is almost similar to what another person said!

1 Like