Im doing a simple lightning spawn test around a center transform. Lightning should spawn in random places when key is pressed. However, all methods using UnityEngine.Random.Range (float,float) to determine spawn location returns same number.
Below is the simple code (with extra Debug.Log number generation thrown in for testing:
Please see attached screen dump of output results. I was expecting to get random numbers on each debug log on each key press. Randomization seems to happen between every UnityEngine.Random.Range call, but the same line of code produces the same result between key presses. I am now very confused.
I should mention that with some irregulary the key press DOES generate a spawn in a random position, before going back to producing 15-40 spawns in the same place. Very confusing.
Something is setting the state of the number generator through Random.state or Random.InitState. Find that. That is what is causing the numbers to be the same most of the time.
If you wanted to avoid removing the seed reset which could be there for some good reason, or you can’t find it (likely in a compiled assembly then), you could generate a seed from a separate source like System.Random and use InitState to give yourself a new state just for your spawning. You should probably store and restore the existing state before and after all of this.
When CTRL-F searching Visual Studio using search scope = ‘entire project’ for occurances of “random.state” or “random.initstate” text ignoring capital letters match I find zero occurances.
Yesterday this script behaved as expected, and I’ve made no changes to Random seed myself. I am the only person touching this project.
Am I not getting VS to search all relevant assemblies when using ‘entire project’ to find any culprit script? What else am I missing here?
I assume you mean “entire solution.” It would be searching the C# projects it’s aware of, so code from packages wouldn’t be searched if C# project generation is disabled for those.
Alternatively, you can use the ... button to select the project’s root folder or any local folder you’re pulling packages from, and perform a simple text search there.
Tried testing - Indeed setting state before every Random.Range call fixes the issue.
Went back and did a root folder text search for all files contain random.initstate and “random.state”. All but one project package file revert back to previous state.
LightUtility.cs located in project\Library\PackageCache\com.unity.render-pipelines.universal@14.0.10\Runtime\2D is the only file that via method ‘GenerateShapeMesh’ initialize state for deterministic output WITHOUT caching and resetting Random.state before finishing a method call.
I’ve tried inserting code to cache and revert state, but saved changes to the file does not seem to stick.
Alternatively I should randomize Random.state before every Random.Range call in the project. However the amount of times Random.Range is used in the project is extensive to say the least.
For future reference, recent versions of 2022.3 LTS (since 2022.3.28f1) and Unity 6 Preview allow for temporarily modifying packages in the cache. However, making changes stick permanently is typically done by embedding the package with the desired changes.
This specific issue (UUM-65629) was fixed in 2021.3.37f1, 2022.3.22f1, 2023.2.16f1, 6000.0.0b12, as SRP packages like URP are shipped with the editor. Update to the appropriate version (good time to update to the latest version in your stream like 6000.0.13f1 or 2022.3.40f1) to see that fix.
Ah it was the addition of freeform 2D light that did me in, did not realize that that had caused issues in some versions and had since then been fixed.
Thank you kindly for your competent troubleshoot, advice and recommendations, Spy.
Just as a tip, I would rely more on “find usages” rather than search. For instance if someone wrote “Random .state = 1234” that would be legal syntax. Text search won’t find this, but find usages will.
Also, consider using com.unity.mathematics package, it has its own instantiable and lightweight random so you will never run into issues caused by someone or something else elsewhere because of Random’s static nature.
Which is why I had suggested using Shift+F12 (“Find All References” in Visual Studio). There could’ve also been nonsense like using RandomUnity = UnityEngine.Random; Again, only works if C# projects for the projects in question are generated.
Unity Mathematics doesn’t have an equivalent to insideUnitCircle/insideUnitSphere. It’s not a silver bullet on its own.
Here’s a rough and untested translation of some stackoverflow answers:
// https://stackoverflow.com/a/50746409
public static float2 NextRandomPointInsideUnitCircle(this ref Unity.Mathematics.Random random)
{
return math.sqrt(random.NextFloat()) * random.NextSinCos();
}
// https://math.stackexchange.com/a/87238
public static float3 NextRandomPointInsideUnitSphere(this ref Unity.Mathematics.Random random)
{
return MathF.Cbrt(random.NextFloat()) * random.NextRandomPointOnUnitSphere();
}
public static float3 NextRandomPointOnUnitSphere(this ref Unity.Mathematics.Random random)
{
float3 x = new float3(random.NextNormalPair(), random.NextNormalPair().x);
float y = math.length(x);
return math.select(x / y, new float3(1, 0, 0), y < math.EPSILON);
}
public static float2 NextNormalPair(this ref Unity.Mathematics.Random random)
{
return math.sqrt(-2f * math.log(random.NextFloat())) * random.NextSinCos();
}
public static float2 NextSinCos(this ref Unity.Mathematics.Random random)
{
math.sincos(random.NextFloat(0, math.TAU), out float sin, out float cos);
return new float2(sin, cos);
}