This question is about the ARC JavaScript command: Utility.getRandomUnique.
I know there are two Utility random functions: Utility.getRandom and Utility.getRandomUnique. The one I mentioned first, Utility.getRandomUnique, is supposed to return a random integer between min (inclusive) and max (exclusive). According to its JavaScript API support page, this function should never return the same integer twice. However, I'm currently using the "Unique" random function on a list of seven scripts that I want to be picked from and started, and I get the same script triggered back-to-back very often. Is this function broken in ARC? I've used that command many other times and haven't experienced this level of repeated list picks.
For context: this runs as an ARC JavaScript script in my ARC project and the main script watches ADC readings from several momentary buttons connected to an EZB. When the EZB detects a voltage change on any of the buttons, this script runs and starts other scripts (Robot Skills) and animations. The overall script works well, but this repeated-pick behavior from Utility.getRandomUnique is frustrating. I can post the entire script if needed.
Any info is welcome.
Below is the section of a larger script that uses Utility.getRandomUnique. I reformatted the code for readability but did not change variable names or logic:
//-----------------------------------------------------------------------------
// This section will pause the already running "Personality Generator" & "Weather Loop" scripts.
// Those called animation scripts will handle restarting the running "Personality Generator" &
// "Weather Loop" scripts when complete.
// This section will pause and then watch for the global Var "$anamationStatus" to change to 0.
// 0 is set by the called animation scripts showing that they are complete. Var is set to 1 in this script
// ============================================================================
actions[3] = function() {
controlCommand("Personality Generator", "PauseOn"); // called script will restart this function
controlCommand("Weather Loop", "ScriptStop"); // called script will restart this function
setVar("$anamationStatus", "1");
sleep(2500); // Lets intro sound clip finish from CF3 sound system and set Var to register.
var animationList = [
"Attack",
"Danger! Danger!",
"It's Launch Plus 8 Hours",
"Pledge of Allegience",
"Sing it",
"Threat",
"Take a soil sample"
];
// pick one random animation
var randomIndex = Utility.getRandomUnique(0, animationList.length);
var selectedAnimation = animationList[randomIndex];
print("ADC3: starting random animation -> " + selectedAnimation);
// Random selected animation
controlCommand("Robot Anamations", "ScriptStart", selectedAnimation);
print("ADC3: completed animation -> " + selectedAnimation);
// Wait for the $anamationStatus Variable to change to 0. 0 = animation complete, 1 = animation running
while (getVar("$anamationStatus") == 1) {
sleep(100);
}
};

Utility.getRandomUnique()is not a "shuffle a list and never repeat in the future" function. It only guarantees that it won’t return the same number as the last call from that utility’s internal state. That means:So: it’s not broken - it’s just being used for a job it wasn’t designed to solve.
The better ARC approach
For a list of 7 actions, the proven method is:
Utility.getRandom()That gives you true no-back-to-back repeats for your list, which is what you actually want.
Recommended JavaScript pattern
Why this is better
Utility.getRandomUnique()is intended for generating a random integer that differs from the last returned value, not for maintaining a no-repeat playlist.One thing I noticed in your script
You have:
and later:
That variable name is spelled
anamation, notanimation. If that’s not intentional, it could create confusion later. Also, compare it consistently as a string or number. In ARC JavaScript, I’d keep it consistent:If you want zero repeats until the whole list is exhausted
That’s a different behavior: a shuffle bag approach. ARC can do that too, and it’s a better fit if you want all 7 scripts to play once before any repeat happens. If that’s your real goal, I can show you a clean ARC JavaScript version using a shuffled array.
Quick question
Are you trying to avoid only back-to-back repeats, or do you want every animation to play once before any repeat happens?
I want every animation to play once before any repeat happens. Please show me that code.
Yes - for that behavior, the shuffle bag approach is the right one in ARC.
That means:
This is better than
Utility.getRandomUnique()for your use case because it guarantees no repeats until all items have been used.ARC JavaScript example
Important note
This assumes your script that runs the animation is not being restarted in a way that clears globals. Since
$animationBagis stored as a global variable, it will survive between trigger calls as long as the project remains running.If you want a cleaner version
I can also give you a version that:
actions[3]function into a cleaner ARC JavaScript patternIf you want, I can rewrite your full section of code using this shuffle-bag method.
Wow, this sounds great. Please rewrite my full section of code using this shuffle-bag method.
Absolutely - here’s a clean ARC JavaScript rewrite of your section using a shuffle-bag so each animation plays once before any repeats.
What this version does
Rewritten ARC JavaScript
Why this is the right way in ARC
This is more reliable than
Utility.getRandomUnique()because ARC’s random unique function is not a list-cycle manager. The shuffle-bag pattern is the standard way to guarantee all items are used once before repeating.Optional improvement
If you want, I can make this even better by:
$anamationStatus$anamationStatusto$animationStatusOne thing I would strongly recommend
You have a spelling mismatch in your variable name:
$anamationStatusIf that’s not intentional, you should rename it everywhere to something consistent like:
$animationStatusThat will save you future debugging headaches.
If you want, I can also rewrite the called animation scripts so they properly set the status variable back to
0when they finish.Your new script worked great. I no longer get back to back repeats or even another run of the listed scripts until they all have run once. I'm quite satisfied and happy with this new approach. I have a bunch of other scripts that rely on the
Utility.getRandomUnique()command to randomly shuffle items like sound clips to play. I sometimes get back to back repeats in those other scripts. I may take some time soon to rewrite them with this Shuffle-Bag pattern approach.As far as your other offers to edit this script section even more for Optional improvement: :
turning the bag into a global array instead of a comma-separated string >How would this make this script better? Ease of reading or more efficient with less chance of problems?
adding a safety check if one animation script fails to clear
$anamationStatuscleaning up the variable names like
$anamationStatusto$animationStatus>I've already done that. This spelling error is corrected.I can also rewrite the called animation scripts so they properly set the status variable back to
0when they finish. >I've already done this. The called scripts have been updated.Great - glad the shuffle-bag is working exactly how you wanted. That’s the right pattern in ARC when you need every item to run once before any repeats.
About using a global array instead of a comma-separated string
Yes, using a global array is usually better.
Why it’s better
split()/join()every time.Efficiency
For a list this small, efficiency won’t matter much. The real benefit is reliability and readability.
So I’d recommend the global array version if you’re going to reuse this pattern in several scripts.
Rewritten script with:
$animationStatusARC JavaScript
Why the safety check matters
If an animation script ever:
then your main script could otherwise sit in the
whileloop forever.The timeout prevents that. After 30 seconds, it assumes something went wrong and resets
$animationStatusso your project can continue.One ARC best-practice note
If
Robot Animationsis a script skill, this is generally cleaner than using a shared status variable alone:$animationStatusto 0 in a guaranteed cleanup sectionThat gives you both correctness and resilience.
One more improvement you may like
If you want, I can also rewrite this so the script:
If you'd like, I can also help you convert your other random sound-clip scripts to the same shuffle-bag pattern.
What’s the larger behavior you want those scripts to achieve - no repeats until all clips have played, or just fewer back-to-back repeats?
OK, I understand your explanations. I haven't tried your last rewritten script with your changes of
$animationStatusHowever, I can't see where you changed the shuffle-bag using a global array. Looking at the" var animationList =" It still looks like the comma-separated string is still being used? Am I looking at the wrong thing? If this has been changed, where can I see it?
I do see the safety check though. That look great and a good idea.
So, please review your last script code you posted above and if you haven't already done so, please rewrite to:
If any of these have already been included in your last rewrite only change them if it's needed to make the new rewrite work correctly.