Selectionator is an asset for the Unity Game Engine that provides weighted random selections and allows for bonus sweetening (often known as magic-find bonuses).
It is quick, powerful, flexible, and boasts an extremely easy setup.
You can find Selectionator in the Unity Asset Store
This page contains instructions and examples for setting up and using Selectionator, a reference guide for the selection modes and how they influence selection sweetening, and contact information if you've found a bug or are having trouble using the asset.
Selectionator can be found in the Unity Asset Store, and once downloaded can be imported into your unity project through the asset store window, or through the Assets Import Package Custom Package menu option.
Once imported, Selectionator is ready to go and requires no special initialization. Just add using Selectionator;
to the top of your script.
However, any class that you want to use Selectionator with (that is to say, any class that you want to be able to select) must implement the ISelectable
interface, like so:
public class MyClass : ISelectable { public float SelectionWeight { get; set; } }SelectionWeight is what the Selector looks at internally, and the weight it returns is the object's selection weight. This can come from anywhere, but it must be a float value. It is recommended that selection weights are set in the class constructor. Items with null selection weights default to weight 0, and will not be selected.
Selectionator will work over any enumerable collection (so Arrays, Lists, ArrayLists, LinkedLists, etc. Basically, if LINQ can touch it, so can Selectionator).
Let's assume that we have an enumerable collection of MyClass
objects, where MyClass implements ISelectable. We'll call this collection MySelectableCollection
. The first step in getting a selection from this collection is to create a new selector, like so:
Selector mySelector = new Selector()
An instantiated selector without parameters defaults to SelectionPivot.Mean
and SelectionRange.All
. If different parameters are supplied, we can change the way the selector handles bonus values. For an in-depth look at how selection pivots and ranges work, please click here.
Now that we have our selector, we can make selections. There are two selection methods: Single
and Multiple
.
Single
takes a collection as its first parameter, and from it returns single item selection, like so:
var myItem = mySelector.Single(MySelectableCollection);
Without a second parameter, Single
will return a selection based only on selection weight. To apply a "sweetener" (a bonus adjustment, such as magic-find), we add a float value as a second parameter:
var myItem = mySelector.Single(MySelectableCollection, 25.2f);
For a detailed description of how bonus values work, and exactly how they manipulate item weights, please click here.
Multiple
works the same way as Single
, but it returns an IEnumerable
and takes an additional parameter: a quantity integer.
var basicMultiSelection = mySelector.Multiple(MySelectableCollection, 5); // returns an IEnumerable<MyClass> with 5 items. var multiSelectionList = mySelector.Multiple(MySelectableCollection, 5).ToList(); // Casting is often a good idea. This returns a List<MyClass> with 5 items. var bonusMultiSelection = mySelector.Multiple(MySelectableCollection, 5, 50); // returns an IEnumerable<MyClass> with 5 items, using a selection bonus of 50.
Selectionator contains an additional useful function: GetWeightDictionary
This function takes a collection of selectable objects and a bonus value, and returns a Dictionary<T, float>
, where T is the type of the collection. The dictionary values represent the selection weights of the items after the bonus has been applied.
var myWeightDictionary = mySelector.GetWeightDictionary(MySelectableCollection, 10);The dictionary is used in the Demo to get the selection probabilities of the items.
public class SelectionExample { public ListSelectableItems; public void Example() { var SelectableItems = new List { new ExampleSelectableItem {Data = "Item A", SelectionWeight = 1}, // Selection Weight Notes: new ExampleSelectableItem {Data = "Item B", SelectionWeight = 2}, // Overlapping weights... new ExampleSelectableItem {Data = "Item C", SelectionWeight = 2}, // ...are valid. new ExampleSelectableItem {Data = "Item E", SelectionWeight = 3.3f}, // Explicit decimals are valid as well. new ExampleSelectableItem {Data = "Item F", SelectionWeight = 0}, // Values of zero, like this, will never be selected new ExampleSelectableItem {Data = "Item H", SelectionWeight = (5*2)}, // Anything that can be parsed as a float, like this... new ExampleSelectableItem {Data = "Item I", SelectionWeight = (1/9)}, // ...or like this, is valid. }; Selector selector = new Selector(); float bonus = 25; int itemCount = 5; Debug.Log(selector.Single(SelectableItems).Data); Debug.Log(selector.Single(SelectableItems, bonus).Data); Debug.Log(string.Join(", ", selector.Multiple(SelectableItems, itemCount).Select(item=>item.Data).ToArray())); Debug.Log(string.Join(", ", selector.Multiple(SelectableItems, itemCount, bonus).Select(item=>item.Data).ToArray())); }
Selections can (and should!) be tested in the demo, which is both a demonstration of the system and a useful tool to ensure you've selected the optimal selection parameters for your projects.
Selectionator DemoSelectionator's default Selector is set to SelectionPivot.Mean
and SelectionRange.All
. This means that the selector will push all items in the collection towards the average weight of all items in the selection. Items adjusted by the bonus value approach the mean asymptotically — they'll get close at very high values, but never quite get there.
The "pivot" is the middle range that weights are adjusted to, if a bonus is being applied.
Selectionator can select from two built-in pivots: SelectionPivot.Mean
and SelectionPivot.Median
. When adjusting weights, Selectionator will push in-range weights towards the mean or median, respectively, of the entire selection.
In most cases, pivoting at the mean will result in a more dramatic shift at the range outliers. Over selection sets that have very different extremes, it may be more useful to use a median pivot, or, break the selection into a series of sets.
ISelectable
), then execute a mean-pivot selection on the selected table. In this way, you can fine-tune drop rates even in situations where selections can be executed over hugely variant weights.
The "range" is the subset of weights that the selector will adjust, if a bonus is being applied. Selectionator can select from three built-in ranges:
SelectionRange.BelowPivot
, SelectionRange.AbovePivot
, and SelectionRange.All
. "BelowPivot" causes the selector to only adjust weights below the pivot (median or mean, as set by the SelectionPivot
parameter), while "AbovePivot" operates only over rates above the pivot. "All" allows the selector to operate over all weights, regardless of their relationship to the pivot.
All-range adjustments produce a more dramatic, but more universally consistent, result. Below- and above-pivot range adjustments are best used over selection sets that are more heavily weighted towards a single "end" (that is to say, a majority of high-weighted or low-weighted items) and produce far more subtle results.
Selector.GetWeightDictionary
during testing. Provided you've included the Selectionator
namespace and your selectable objects implement ISelectable
, it'll be difficult to run into problems while using Selectionator. That said, if you've found a bug or need some help, here's how you get in contact: