Selecting Distinct Values

Often, it's essential to ensure that each value you select from a set is unique. While selecting distinct values alters the inherent probabilities, this guide will walk you through a straightforward approach to achieve this.


Selecting Unique Rewards

Imagine a scenario where you'd like to offer players three unique rewards upon completing a game level.

Firstly, let's establish a basic Reward class. This class will:

  • Contain details about the in-game currency
  • Provide relevant information to the drawer through the info provider interface

Basic Reward Class

using System;
using RNGNeeds;

[Serializable]
public class Reward : IProbabilityItemInfoProvider
{
    public string currency;
    public int value;
    public string ItemInfo => $"{currency} ({value.ToString()})";
}

Subsequently, we'll introduce a LevelCompletionRewards component that will be responsible for housing our range of potential rewards.

Add a ProbabilityList for Rewards

using UnityEngine;
using RNGNeeds;

public class LevelCompletionRewards : MonoBehaviour
{
    public ProbabilityList<Reward> rewards;
}

After attaching the component to a GameObject, you can begin shaping your array of rewards.

Distinct Selection - List

With the reward pool in place, it's time to introduce the logic ensuring that only distinct rewards are chosen. Incorporate the following segment into the LevelCompletionRewards component.

Add Distinct Selection Logic

using UnityEngine;
using RNGNeeds;
using System.Collections.Generic;

public class LevelCompletionRewards : MonoBehaviour
{
    public ProbabilityList<Reward> rewards;

    public List<Reward> PickRewards(int count)
    {
        rewards.SetAllItemsEnabled(true);
        rewards.MaintainPickCountIfDisabled = true;
        
        var pickedRewards = new List<Reward>();
        
        for (var i = 1; i <= count; i++)
        {
            if (!rewards.TryPickValueWithIndex(out var pickedReward, out var pickedIndex)) continue;
            pickedRewards.Add(pickedReward);
            rewards.SetItemEnabled(pickedIndex, false);
        }

        return pickedRewards;
    }
}

Let's break down the PickRewards method:

  • It initializes by ensuring every reward is accessible for selection using .SetAllItemsEnabled(true).
  • The MaintainPickCountIfDisabled property guarantees that each pick will be successful even if disabled items are present in the list.
  • For each desired reward, the method picks a reward, adds it to the list, and then immediately disables it to ensure uniqueness.

To see this in action, invoke the PickRewards method:

Test the distinct selection

var pickedRewards = PickRewards(rewardsToPick);

foreach (var reward in pickedRewards)
{
    Debug.Log(reward.ItemInfo);
}

// An example console output with three unique rewards could be:
// Gold (100)
// Diamonds (5)
// StarDust (75)

Post-testing, examining the list will reveal that chosen items have been disabled.

Distinct Selection - Pick

In conclusion, by momentarily disabling each item post-selection, this method efficiently curates a set of entirely unique items from the list.