The Mixed Reality Forums here are no longer being used or maintained.
There are a few other places we would like to direct you to for support, both from Microsoft and from the community.
The first way we want to connect with you is our mixed reality developer program, which you can sign up for at https://aka.ms/IWantMR.
For technical questions, please use Stack Overflow, and tag your questions using either hololens or windows-mixed-reality.
If you want to join in discussions, please do so in the HoloDevelopers Slack, which you can join by going to https://aka.ms/holodevelopers, or in our Microsoft Tech Communities forums at https://techcommunity.microsoft.com/t5/mixed-reality/ct-p/MicrosoftMixedReality.
And always feel free to hit us up on Twitter @MxdRealityDev.
Finding a random point inside the spatial map?
I'm trying to find random points inside of the spatial map to spawn objects. Any ideas as to how this can be accomplished? As of now, things can spawn outside of the map because my points are completely random.
Best Answers
-
OptionsMicheal ✭✭
So, I stumbled across this: http://www.softimageblog.com/archives/115
I'm looking to do a sphereCastAll from evenly distributed points located at a user's head.
I'm trying to think through the implementation now, and port the golden spiral script to C#. Someone with more experience may be able to implement this faster, but I'll share whatever I have if I get to it first.
5 -
OptionsMicheal ✭✭
I was able to implement the golden spiral located at http://www.softimageblog.com/archives/115.
The C# code is as follows:
void CreatePoints() { float N = 50; // Numbers of points to spawn float y; // Used to calculate y float r; // Used to calculate the radius float phi; // Used to calculate the golden number float inc = Mathf.PI * (3 - Mathf.Sqrt(5)); float off = 2 / N; for (var k = 0; k < N; k++) { y = k * off - 1 + (off / 3); r = Mathf.Sqrt(1 - y * y); phi = k * inc; _pts.Add(new Vector3(Mathf.Cos(phi) * r, y, Mathf.Sin(phi) * r)); } }
I did my best to comment, but my knowledge of the mathematics is still a work in progress. (If someone wants to comment this out better, it'd be much appreciated )
I then created a few variables:
public struct SpawnRange // A Struct is born to hold the starting and end points from my raycast { public Vector3 origin; public Vector3 endpoint; } public GameObject yourGameObject; // The enemy prefab to be spawned. public float spawnTime = 3f; // How long between each spawn. public float updateTime = 3f; // How long between updates to _pts Camera cam; // Stores the active camera to be used for location purposes Vector3 camTransform; // Stores the camera's position once we know it. [Tooltip("Select the layers raycast should target.")] public LayerMask RaycastLayerMask = Physics.DefaultRaycastLayers; // Lets us define the layers to mask in the editor [Tooltip("Multiplies by this number to control the size of the sphere")] public float sizeReduction = 1; // Controls the size of the sphere in the inspector private List<Vector3> _pts = new List<Vector3>(); // A list to hold all the points found on the spher private List<SpawnRange> ranges = new List<SpawnRange>(); // A list to hold my struct with acceptable spawn ranges
Now that we're set up, we can create the method we will use to update these ranges as the user moves around and into different rooms.
void UpdateSpawnRanges() { Vector3 direction; // Stores the direction our rays should go ranges.Clear(); // Clears the existing list of ranges before adding the new ones camTransform = cam.transform.position - new Vector3(0,0,0.5f); // Lowers the location of our raycasting sphere in the world foreach (var pt in _pts) // Every point in our list { RaycastHit hitInfo; // Stores our raycast's hit direction = (pt * (sizeReduction + 0.75f) - (pt * sizeReduction)).normalized; // Creates a big and a small sphere based on the points generated, and calculates the direction Physics.SphereCast((pt * sizeReduction) + camTransform, 4f, direction, out hitInfo, 20f, Physics.DefaultRaycastLayers); // Does the actual spherecast SpawnRange spawnRange; // Creates our struct to store the range spawnRange.origin = (pt * sizeReduction) + camTransform; // Uses the location of our small sphere as the first point spawnRange.endpoint = hitInfo.point; // Uses the location that our spherecast hit to determine the end point ranges.Add(spawnRange); // Adds the above range to one big list } }
Now for the spawner that actually instantiates our gameobject at a random location.
void Spawn() { float randomX; // Used to hold my random X float randomY; // Used to hold my random Y float randomZ; // Used to hold my random Z // Picks a random point range from our list of ranges SpawnRange randomRange = ranges[Random.Range(0, ranges.Count)]; // Sets the varibales to randomize the location. randomX = Random.Range(randomRange.origin.x, randomRange.endpoint.x); randomY = Random.Range(randomRange.origin.y, randomRange.endpoint.y); randomZ = Random.Range(randomRange.origin.z, randomRange.endpoint.z); // Create an instance of the prefab at the randomly selected spawn point's position and rotation. Instantiate(yourGameObject, new Vector3(randomX, randomY, randomZ), Quaternion.identity); }
Finally in Start, we can set everything up.
void Start() { InvokeRepeating("UpdateSpawnRanges", 0, updateTime); // Calls the update function immeditately at start and updates per updateTime InvokeRepeating("Spawn", spawnTime, spawnTime); // Call the Spawn function after a delay of the spawnTime and then continue to call after the same amount of time. cam = (Camera)GameObject.Find("Main Camera").GetComponent(typeof(Camera)); // Finds the camera component of our Main Camera CreatePoints(); // Creates the points that we will use throughout our script }
It still can definitely use some improvements, and it doesn't exactly work well when the spatial mapping disappears from black pieces of furniture in your room, but it's definitely a solid script to make sure _most _things spawn within your room at random spots.
6
Answers
Random angle + distance should work.
Pick a random rotation from the user's head and a random distance out from that rotation to the room mesh.
I'm interested in seeing what other ideas people have. I've been tackling this issue in my application as well. Assuming you're using Unity, my current thought process is this:
Another approach that I'm looking at it tying the random placement in with the path finding I already have implemented. It takes the spatial mesh and generates a grid graph (with height map) which you can use for placement. The grid points marked as inaccessible, simply don't place something there.
So, I stumbled across this: http://www.softimageblog.com/archives/115
I'm looking to do a sphereCastAll from evenly distributed points located at a user's head.
I'm trying to think through the implementation now, and port the golden spiral script to C#. Someone with more experience may be able to implement this faster, but I'll share whatever I have if I get to it first.
I was able to implement the golden spiral located at http://www.softimageblog.com/archives/115.
The C# code is as follows:
I did my best to comment, but my knowledge of the mathematics is still a work in progress. (If someone wants to comment this out better, it'd be much appreciated )
I then created a few variables:
Now that we're set up, we can create the method we will use to update these ranges as the user moves around and into different rooms.
Now for the spawner that actually instantiates our gameobject at a random location.
Finally in Start, we can set everything up.
It still can definitely use some improvements, and it doesn't exactly work well when the spatial mapping disappears from black pieces of furniture in your room, but it's definitely a solid script to make sure _most _things spawn within your room at random spots.
Ah, thanks for the code. For my purpose I'm thinking something simpler, but if that method fails I'll be looking at this spiral method.
Could you put out a large bounding box with collision, then raycast out at a random angle? Then place it on a random position between the position of your head and the position of your raycast hit?
Theoretically, yes, that should work, just reiterate if the random spot failed.
In my mind, the idea should be to test to make sure your instanced object is within the spatial area with the least amount of checks. The spiral method looks like it'll solve the issue, but depending on your needs, something computationally simpler may do the trick. Of course the method to use also depends on how often you'll be doing this task and if it is during the initialization or during active play where it may impact frame rate.
I'm having the user place the "goal," and then from there am having a ray cast at various angles performed to a certain distance, any that are good (no hits) are placed into an array, and then a random index is chosen for that array. This works well enough for my use. The downside of any raycasting method is that it assumes you only want a random spot within the visible area. If you want to place an object behind something, this method will fail as a raycast is inherently a line of sight test.
That's why a navmesh or grid graph path finding design may be better, depending on your needs but can be a lot more computationally expensive (especially if you're updating the spatial mesh).