When visible surfaces of two objects are fully aligned, the bounding boxes seem to blink in and out of existence from one frame to another. Why is that?</summary>
<summary><strong>Q:</strong> When visible surfaces of two objects are fully aligned, the bounding boxes seem to blink in and out of existence from one frame to another. Why is that?</summary>
This is due to a common graphics problem called *z-fighting*. This occurs when the shader can't decide which of the two surfaces to draw on top of the other, since they both have the exact same distance from the camera. To fix this, simply move one of the objects slightly so that the two problematic surfaces do not fully align.
## Randomization
<details>
<summary><strong>Q:</strong>
<summary><strong>Q:</strong> How can I have multiple sets of prefabs in a foreground placement Randomizer, and on every Iteration select one from each set?
</summary>
This question is an example of more complex functionality that can be achieved by applying slight modifications to the provided sample Randomizers, or by creating completely custom ones using the powerful Parameters provided in the package.
Here, we have a variety of options toward achieving the described outcome. One simple method could be to add several more `GameObjectParameter` fields inside of the provided sample `ForegroundObjectPlacementRandomizer`. Each of these Parameters could hold one of our object lists. Then, on each iteration, we would fetch one prefab from each of the lists using the `Sample()` function of each Parameter.
The above solution can work but it is not modular enough, with the lists of prefabs not being reusable in other Randomizers.
A better approach can be to define each prefab list separately as a scriptable object asset, and then just reference those scriptable objects inside of our foreground Randomizer. To do this, we first define a `PrefabCluster` class to hold a list of prefabs.
```C#
using UnityEngine;
using UnityEngine.Perception.Randomization.Parameters;
We can now create a cluster asset using the ***Assets -> Create -> Test -> PrefabCluster** menu option and populate its list of prefabs. Each cluster contains one `GameObjectParameter`, which will hold the list of prefabs and provide us with a `Sample()` function.
I need to randomize the rotation of my objects in such a way that they always face the camera, but rotate in other directions. How can I achieve that with a Randomizer?</summary>
To be able to edit these clusters with the same editor UI available for Randomizers, you will also need to add an empty custom editor for the `PrefabCluster` class that extends our bespoke `ParameterUIElementsEditor` class:
```C#
using UnityEditor;
using UnityEditor.Perception.Randomization;
[CustomEditor(typeof(PrefabCluster))]
public class PrefabClusterEditor : ParameterUIElementsEditor { }
```
Note that any editor scripts must be placed inside a folder named "Editor" within your project. "Editor" is a special folder name in Unity that prevents editor code from compiling into a player during the build process. For example, the file path for the `PrefabClusterEditor` script above could be ".../Assets/Scripts/Editor/PrefabClusterEditor".
The ***Inspector*** view of a prefab cluster asset looks like below:
<palign="center">
<imgsrc="images/prefab_cluster.png"width="400"/>
</p>
Now all that is left is to use our prefab clusters inside a Randomizer. here is some sample code:
public class ClusterRandomizer : UnityEngine.Perception.Randomization.Randomizers.Randomizer
{
public PrefabCluster[] clusters;
protected override void OnIterationStart()
{
//select a random prefab from each cluster
foreach (var cluster in clusters)
{
var prefab = cluster.clusterPrefabs.Sample();
//do things with this prefab, e.g. create instances of it, etc.
}
}
}
```
This Randomizer takes a list of `PrefabCluster` assets, then, on each Iteration, it goes through all the provided clusters and samples one prefab from each. The ***Inspector*** view for this Randomizer looks like this:
<summary><strong>Q:</strong> How can I specify an exact number of objects to place using the sample foreground object placement Randomizer? </summary>
The provided `ForegroundObjectPlacementRandomizer` uses Poisson Disk sampling to find randomly positioned points in the space denoted by the provided `Width` and `Height` values. The distance between the sampled points will be at equal to `Separation Distance`. The number of sampled points will be the maximum number of points in the given area that match these criteria.
Thus, to limit the number of spawned objects, you can simply introduce a hard limit in the `for` loop that iterates over the Poisson Disk samples, to break out of the loop if the limit is reached. For example:
```C#
protected override void OnIterationStart()
{
var seed = SamplerState.NextRandomState();
//retrieve points using Poisson Disk sampling
var placementSamples = PoissonDiskSampling.GenerateSamples(
var offset = new Vector3(placementArea.x, placementArea.y, 0f) * -0.5f;
var limit = 50;
//maximum number of objects to place
var instantiatedCount = 0;
//iterate over all points
foreach (var sample in placementSamples)
{
if (instantiatedCount == limit)
break;
instantiatedCount ++;
var instance = m_GameObjectOneWayCache.GetOrInstantiate(prefabs.Sample());
instance.transform.position = new Vector3(sample.x, sample.y, depth) + offset;
}
placementSamples.Dispose();
}
```
This will guarantee an upper limit of 50 on the number of objects. To have exactly 50 objects, we need to make sure the `Separation Distance` is small enough for the given area, so that there is always at least 50 point samples found. Experiment with different values for the distance until you find one that produces the minimum number of points required.
</details>
<details>
<summary><strong>Q:</strong> How can I avoid object overlap with the sample foreground object placement Randomizer?</summary>
There are a number of ways for procedurally placing objects while avoiding any overlap between them, and most of these methods can be rather complex and need to place objects in a sequence. All the modifications to the objects (like scale, rotation, etc.) would also need to happen before the next object is placed, so that the state of the world is fully known before each placement.
Here, we are going to introduce a rather simple modification in the sample foreground placement code provided with the package, which works by finding a desirable separation distance based on the list of given prefabs. Based on the value given for `Non Overlap Guarantee`, this Randomizer can either reduce the amount of overlap or completely remove overlap.
```C#
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Perception.Randomization.Parameters;
using UnityEngine.Perception.Randomization.Randomizers;
using UnityEngine.Perception.Randomization.Randomizers.Utilities;
using UnityEngine.Perception.Randomization.Samplers;
public class NoOverlapForegroundObjectPlacementRandomizer : Randomizer
{
public float depth;
[Tooltip("Range of scales used for objects. All objects in each frame will use the same scale.")]
public FloatParameter scaleParameter = new FloatParameter { value = new UniformSampler(4, 8) };
public Vector2 placementArea;
public GameObjectParameter prefabs;
[Tooltip("Degree to which we can guarantee that no objects will overlap. Use 1 for no overlap and smaller values (down to 0) for more dense placement with a possibility of some overlap.")]