Getting Started with Ultimate Dice Roll Toolkit
This guide will help you start using the Ultimate Dice Roll Toolkit in your Unity projects. The toolkit provides comprehensive dice rolling functionality through a single static API class with all the rolling methods you need.
Table of Contents
Installation
- Project Setup
- Namespace Import
- Basic Test
Dice Configurations
- DiceConfiguration ScriptableObjects
- RollAdvanced Method
- Target Evaluation
Conditional Rules
- Rule Processing
- RollWithRules Method
- Trigger and Action Types
Opposed Rolls
- Contest Resolution
- Resolution Modes
- Quick Methods
Session Management
- Modifier Sessions
- Multi-Dice Sessions
- Session Templates
Probability Analysis
- Monte Carlo Calculations
- Statistical Results
- Distribution Analysis
Import and Export
- JSON Configuration Export
- Configuration Import
- File Operations
Seeded Operations
- Deterministic Rolling
- Seed Management
- Reproducible Results
Installation
Project Setup
Copy the entire "Ultimate Dice Roll Toolkit" folder into your Unity project's Assets directory. The toolkit is self-contained and has no external dependencies.
Namespace Import
Add the namespace to any script where you want to use dice rolling:
using UnityEngine;
using UltimateDiceToolkit;
public class MyGameScript : MonoBehaviour
{
void Start()
{
// Now you can use DiceAPI methods
int result = DiceAPI.Roll(20);
Debug.Log($"Rolled: {result}");
}
}
Basic Test
Test your installation with this simple verification script:
using UnityEngine;
using UltimateDiceToolkit;
public class DiceTest : MonoBehaviour
{
void Start()
{
// Test basic rolling
int d20 = DiceAPI.Roll(20);
Debug.Log($"d20: {d20}");
// Test with modifier
int d20Plus5 = DiceAPI.Roll(20, 5);
Debug.Log($"d20+5: {d20Plus5}");
// Test advantage
int advantage = DiceAPI.RollAdvantage(20);
Debug.Log($"Advantage d20: {advantage}");
}
}
Basic Rolling Methods
DiceAPI.Roll
The fundamental method for rolling a single die:
Method Signature
public static int Roll(int sides, int modifier = 0, bool useSession = true)
Parameters
- sides: Number of sides (2-1000, automatically clamped)
- modifier: Fixed number added to roll (optional)
- useSession: Whether to consume accumulated session modifiers (default: true)
Examples
// Basic rolls
int d6 = DiceAPI.Roll(6); // 1-6
int d20 = DiceAPI.Roll(20); // 1-20
int d100 = DiceAPI.Roll(100); // 1-100
// With modifiers
int attack = DiceAPI.Roll(20, 5); // 1d20+5 (6-25)
int damage = DiceAPI.Roll(8, 3); // 1d8+3 (4-11)
// Without session modifiers
int pure = DiceAPI.Roll(20, 0, false); // Ignores session
DiceAPI.RollMultiple
Roll multiple dice of the same type:
Method Signature
public static int[] RollMultiple(int sides, int count, int modifier = 0, bool useSession = true, RollMode mode = RollMode.Simultaneous)
Examples
// Roll 3d6
int[] rolls = DiceAPI.RollMultiple(6, 3);
int total = rolls.Sum(); // Need using System.Linq;
// Roll 4d8 with +2 on each die
int[] bonusRolls = DiceAPI.RollMultiple(8, 4, 2);
// Sequential mode (currently same as simultaneous)
int[] sequential = DiceAPI.RollMultiple(6, 3, 0, true, RollMode.Sequential);
Advantage and Disadvantage
D&D 5e style advantage/disadvantage mechanics:
Method Signatures
public static int RollAdvantage(int sides, int modifier = 0, bool useSession = true)
public static int RollDisadvantage(int sides, int modifier = 0, bool useSession = true)
Examples
// Advantage: roll twice, take higher
int advRoll = DiceAPI.RollAdvantage(20, 3);
// Disadvantage: roll twice, take lower
int disRoll = DiceAPI.RollDisadvantage(20, 3);
// Both methods automatically log the two rolls made
Advanced Rolling Types
Exploding Dice
Dice that continue rolling when maximum value is rolled:
Method Signature
public static RollResult RollExploding(int sides, int maxExplosions = 10, int modifier = 0, bool useSession = true)
Examples
// Basic exploding d6
RollResult exploding = DiceAPI.RollExploding(6);
Debug.Log($"Exploding d6: {exploding.total}");
Debug.Log($"Explosions: {exploding.explosionCount}");
// Limited explosions with modifier
RollResult limited = DiceAPI.RollExploding(10, 3, 2);
if (limited.explosionCount > 0)
{
Debug.Log($"Individual rolls: {string.Join(", ", limited.individualRolls)}");
}
Dice Pools
Roll multiple dice and count successes above a threshold:
Method Signature
public static RollResult RollPool(int sides, int poolSize, int threshold = 0, int modifier = 0, bool useSession = true)
Examples
// World of Darkness style: 5d10, count 8+ as successes
RollResult wodPool = DiceAPI.RollPool(10, 5, 8);
Debug.Log($"Successes: {wodPool.successCount}");
Debug.Log($"Individual dice: {string.Join(", ", wodPool.individualRolls)}");
// Auto-threshold (calculated based on die size)
RollResult autoPool = DiceAPI.RollPool(6, 4); // Threshold auto-set
Debug.Log($"Threshold used: {autoPool.poolThreshold}");
Drop Mechanics
Roll multiple dice and drop the highest or lowest:
Method Signature
public static RollResult RollDrop(int sides, int diceCount, int dropCount, DropType dropType = DropType.Lowest, int modifier = 0, bool useSession = true)
Examples
// Classic 4d6 drop lowest (for D&D ability scores)
RollResult abilityScore = DiceAPI.RollDrop(6, 4, 1, DropType.Lowest);
Debug.Log($"4d6 drop lowest: {abilityScore.total}");
Debug.Log($"Kept rolls: {string.Join(", ", abilityScore.individualRolls)}");
Debug.Log($"Dropped: {string.Join(", ", abilityScore.droppedRolls)}");
// Drop highest for penalty effect
RollResult penalty = DiceAPI.RollDrop(8, 3, 1, DropType.Highest, 2);
Weighted Rolling
Roll with weighted probability distributions:
Method Signature
public static RollResult RollWeighted(int sides, WeightAlgorithm algorithm, int modifier = 0, bool useSession = true)
Available Weight Algorithms
- WeightAlgorithm.Normal - Fair distribution
- WeightAlgorithm.BiasHigh - Favor high values
- WeightAlgorithm.BiasLow - Favor low values
- WeightAlgorithm.Dramatic - Favor extremes (1s and max)
- WeightAlgorithm.Bell - Bell curve distribution
Examples
// Bias toward high results
RollResult heroic = DiceAPI.RollWeighted(20, WeightAlgorithm.BiasHigh);
// Dramatic extremes (1s and 20s more likely)
RollResult dramatic = DiceAPI.RollWeighted(20, WeightAlgorithm.Dramatic);
Reroll Mechanics
Reroll specific values, ranges, or conditions:
Method Signature
public static RollResult RollWithReroll(int sides, RerollType rerollType, int[] rerollValues = null, int threshold = 1, int maxRerolls = 1, int modifier = 0, bool useSession = true)
Reroll Types
- RerollType.Exact - Reroll specific values
- RerollType.Below - Reroll values below threshold
- RerollType.Above - Reroll values above threshold
- RerollType.Range - Reroll values within range
Examples
// Reroll 1s
RollResult reroll1s = DiceAPI.RollWithReroll(20, RerollType.Exact, new int[] { 1 });
// Reroll values below 3
RollResult rerollLow = DiceAPI.RollWithReroll(6, RerollType.Below, null, 3);
// Multiple rerolls allowed
RollResult multiReroll = DiceAPI.RollWithReroll(8, RerollType.Exact, new int[] { 1, 2 }, 1, 3);
Dice Configurations
DiceConfiguration ScriptableObjects provide a comprehensive way to define complex dice behavior:
RollAdvanced Method
public static RollResult RollAdvanced(DiceConfiguration config, int modifier = 0, bool useSession = true)
Creating Configurations in Code
// Create a configuration programmatically
var config = ScriptableObject.CreateInstance<DiceConfiguration>();
config.sides = 20;
config.rollType = RollType.Exploding;
config.maxExplosions = 5;
// Use the configuration
RollResult result = DiceAPI.RollAdvanced(config);
Debug.Log($"Result: {result.GetFormattedResult()}");
Available Roll Types
- RollType.Normal - Standard single roll
- RollType.Advantage - Roll twice, take maximum
- RollType.Disadvantage - Roll twice, take minimum
- RollType.Exploding - Continue rolling on maximum value
- RollType.Pool - Roll multiple dice, count successes
- RollType.Drop - Roll multiple dice, drop highest/lowest
Target Evaluation
Evaluate roll results against target numbers:
Method Signature
public static TargetResult RollWithTarget(DiceConfiguration config, TargetConfiguration targetConfig, int modifier = 0, bool useSession = true)
Example
// Create target configuration
var targetConfig = new TargetConfiguration
{
enabled = true,
value = 15,
comparison = ComparisonType.GreaterEqual,
showDegrees = true
};
// Roll against target
TargetResult target = DiceAPI.RollWithTarget(diceConfig, targetConfig);
if (target.success)
{
Debug.Log($"Success! Margin: {target.margin}, Degrees: {target.degrees}");
}
else
{
Debug.Log($"Failed by {Math.Abs(target.margin)}");
}
Conditional Rules
Process conditional rules that trigger based on roll results:
Main Methods
public static (RollResult result, int nextRollModifier) ProcessConditionalRules(RollResult result, ConditionalRule[] rules, int currentModifier = 0)
public static (RollResult result, int nextRollModifier) RollWithRules(DiceConfiguration config, ConditionalRule[] rules, int modifier = 0, bool useSession = true)
Example Rule Creation
// Create a critical hit rule
var critRule = ScriptableObject.CreateInstance<ConditionalRule>();
critRule.ruleName = "Critical Hit";
critRule.trigger = new TriggerConfiguration { type = TriggerType.OnMax };
critRule.action = new ActionConfiguration
{
type = ActionType.MultiplyResult,
multiplier = 2.0f
};
// Roll with rules
var (result, nextModifier) = DiceAPI.RollWithRules(config, new[] { critRule });
if (result.triggeredRules.Length > 0)
{
Debug.Log($"Rules triggered: {string.Join(", ", result.triggeredRules)}");
}
Available Trigger Types
- TriggerType.OnMax - Natural maximum roll
- TriggerType.OnMin - Natural 1
- TriggerType.OnValue - Specific number
- TriggerType.OnRange - Within min-max range
- TriggerType.OnDoubles - Two+ dice same value
- TriggerType.OnTriples - Three+ dice same value
- TriggerType.OnSequence - Sequential numbers
- TriggerType.OnSuccess - Meets target number
- TriggerType.OnFailure - Fails target number
- TriggerType.OnMargin - Success/failure by X amount
- TriggerType.OnSum - Total of all dice meets condition
Available Action Types
- ActionType.RollBonus - Add extra dice rolls
- ActionType.AddValue - Add/subtract from result
- ActionType.MultiplyResult - Scale the result
- ActionType.Cascade - Roll the same die again
- ActionType.RerollDie - Replace the result
- ActionType.SetFlag - Mark status effects
- ActionType.ModifyNext - Affect future rolls
Opposed Rolls
Head-to-head contests between two sides:
Main Methods
public static OpposedResult ExecuteOpposedRoll(OpposedRollConfig config)
public static OpposedResult QuickOpposedRoll(DiceConfiguration attackerDice, DiceConfiguration defenderDice, ResolutionMode mode = ResolutionMode.Simple, int marginRequired = 0)
public static OpposedResult QuickAbilityContest(int attackerModifier = 0, int defenderModifier = 0)
Resolution Modes
- ResolutionMode.Simple - Highest total wins
- ResolutionMode.Margin - Must win by specified amount
- ResolutionMode.Contested - Degrees of success/failure
- ResolutionMode.Blackjack - Closest to target without going over
Example
// Quick ability contest
OpposedResult contest = DiceAPI.QuickAbilityContest(5, 3);
Debug.Log($"Winner: {contest.winner}");
Debug.Log($"Attacker: {contest.attackerTotal}, Defender: {contest.defenderTotal}");
Debug.Log($"Margin: {contest.margin}");
// Complex opposed roll
var playerDice = ScriptableObject.CreateInstance<DiceConfiguration>();
playerDice.sides = 20;
playerDice.modifier = 5;
var enemyDice = ScriptableObject.CreateInstance<DiceConfiguration>();
enemyDice.sides = 20;
enemyDice.modifier = 3;
OpposedResult result = DiceAPI.QuickOpposedRoll(playerDice, enemyDice, ResolutionMode.Margin, 5);
Session Management
Modifier Sessions
Track temporary modifiers across multiple rolls:
Session Methods
public static void StartModifierSession()
public static void EndModifierSession()
public static void EndAndClearModifierSession()
public static void ResetSessionModifiers()
public static int GetSessionModifiers()
public static ModifierSource[] GetSessionHistory()
public static string GetSessionSummary()
public static string GetSessionBreakdown()
public static bool HasSessionModifiers()
Example Usage
// Start session and add modifiers
DiceAPI.StartModifierSession();
ModifierSession.AddModifier(2, "Blessing spell");
ModifierSession.AddModifier(-1, "Poisoned");
// Make rolls that consume modifiers
int roll1 = DiceAPI.Roll(20); // Uses +1 total modifier
int roll2 = DiceAPI.Roll(20); // No modifiers left
// Check session state
Debug.Log($"Session summary: {DiceAPI.GetSessionSummary()}");
Debug.Log($"Has modifiers: {DiceAPI.HasSessionModifiers()}");
// Clean up
DiceAPI.EndAndClearModifierSession();
Multi-Dice Sessions
Roll multiple different dice together:
Session Creation Methods
public static DiceSession CreateSession(string sessionName = "New Session")
public static SessionResult RollSession(DiceSession session, int modifier = 0, bool useSession = true)
public static SessionResult RollMultipleDifferent(DiceConfiguration[] configs, string[] labels = null, int modifier = 0, bool useSession = true)
public static SessionResult QuickRollSet(int modifier = 0, bool useSession = true, params (DiceConfiguration config, string label)[] diceSet)
public static (SessionResult result, int nextRollModifier) RollSessionWithRules(DiceSession session, ConditionalRule[] rules, int modifier = 0, bool useSession = true)
Example
// Create session manually
DiceSession session = DiceAPI.CreateSession("Combat Session");
session.AddDice(attackConfig, "Attack Roll");
session.AddDice(damageConfig, "Damage Roll");
// Execute session
SessionResult result = DiceAPI.RollSession(session);
Debug.Log($"Session total: {result.totalSum}");
// Access individual results
var attackResult = result.GetResultByLabel("Attack Roll");
var damageResult = result.GetResultByLabel("Damage Roll");
// Quick roll set
var quickResult = DiceAPI.QuickRollSet(0, true,
(attackConfig, "Attack"),
(damageConfig, "Damage"),
(bonusConfig, "Bonus"));
Session Templates
Pre-built session templates for common scenarios:
Template Methods
public static DiceSession CreateDnDCombatSession(DiceConfiguration attackDie, DiceConfiguration damageDie, string sessionName = "D&D Combat")
public static DiceSession CreateSkillChallengeSession(DiceConfiguration[] skillConfigs, string[] skillNames = null, string sessionName = "Skill Challenge")
public static DiceSession CreateDamageBreakdownSession(DiceConfiguration[] damageConfigs, string[] damageTypes = null, string sessionName = "Damage Breakdown")
Example
// Create D&D combat session
DiceSession combat = DiceAPI.CreateDnDCombatSession(attackDice, damageDice, "Sword Attack");
SessionResult combatResult = DiceAPI.RollSession(combat);
// Create skill challenge
var skills = new DiceConfiguration[] { athletics, acrobatics, investigation };
var skillNames = new string[] { "Athletics", "Acrobatics", "Investigation" };
DiceSession challenge = DiceAPI.CreateSkillChallengeSession(skills, skillNames);
Probability Analysis
Calculate probabilities using Monte Carlo simulation:
Analysis Methods
public static ProbabilityResult CalculateProbability(DiceConfiguration config, int targetValue, ComparisonType comparison, int iterations = 50000)
public static ProbabilityResult CalculateRangeProbability(DiceConfiguration config, int minValue, int maxValue, int iterations = 50000)
public static Dictionary<int, float> GetProbabilityDistribution(DiceConfiguration config, int iterations = 50000)
Example
// Calculate probability of rolling 15+ on d20+5
var config = ScriptableObject.CreateInstance<DiceConfiguration>();
config.sides = 20;
config.modifier = 5;
ProbabilityResult prob = DiceAPI.CalculateProbability(config, 15, ComparisonType.GreaterEqual);
Debug.Log($"Success rate: {prob.percentage:F1}%");
Debug.Log($"Average: {prob.average:F2}");
Debug.Log($"Range: {prob.minimum}-{prob.maximum}");
// Range probability
ProbabilityResult range = DiceAPI.CalculateRangeProbability(config, 10, 20);
Debug.Log($"Probability of 10-20: {range.percentage:F1}%");
// Full distribution
var distribution = DiceAPI.GetProbabilityDistribution(config);
foreach (var kvp in distribution)
{
Debug.Log($"Value {kvp.Key}: {kvp.Value:F2}% chance");
}
Import and Export
Save and load configurations as JSON:
Export Methods
public static string ExportConfiguration(bool includeHistory = false, string description = "")
public static string ExportSpecific(DiceConfiguration[] diceConfigs = null, ConditionalRule[] rules = null, OpposedRollConfig[] opposedConfigs = null, string description = "")
public static bool SaveConfigurationToFile(string filePath, bool includeHistory = false, string description = "")
Import Methods
public static bool ImportConfiguration(string configJson, bool createAssets = true, string assetPath = "Assets/Ultimate Dice Roll Toolkit/Imported/")
public static bool LoadConfigurationFromFile(string filePath, bool createAssets = true, string assetPath = "Assets/Ultimate Dice Roll Toolkit/Imported/")
Example
// Export current system
string json = DiceAPI.ExportConfiguration(true, "My game configuration");
Debug.Log("Exported JSON: " + json);
// Save to file
bool saved = DiceAPI.SaveConfigurationToFile("Assets/MyConfig.json", true, "Backup config");
// Import from JSON
bool imported = DiceAPI.ImportConfiguration(json, true);
// Load from file
bool loaded = DiceAPI.LoadConfigurationFromFile("Assets/MyConfig.json");
Seeded Operations
Enable deterministic, reproducible random sequences:
Seed Methods
public static void InitializeSeed(object seed)
public static void DisableSeed()
public static bool IsSeedActive
public static void ResetSeed()
Example
// Initialize with string seed
DiceAPI.InitializeSeed("MyGameSeed");
Debug.Log($"Seed active: {DiceAPI.IsSeedActive}");
// These will always produce the same sequence
int roll1 = DiceAPI.Roll(20); // Always same result
int roll2 = DiceAPI.Roll(20); // Always same result
// Reset to beginning of sequence
DiceAPI.ResetSeed();
int roll3 = DiceAPI.Roll(20); // Same as roll1
// Return to normal random
DiceAPI.DisableSeed();
int randomRoll = DiceAPI.Roll(20); // Truly random
Important Notes
Session Modifier Consumption
Session modifiers are consumed when used. If you have accumulated +3 from session modifiers and make a roll with useSession=true, those modifiers are consumed and won't apply to subsequent rolls.
Parameter Validation
The API automatically validates and clamps parameters. Dice sides are clamped to 2-1000, dice counts to 1-100, etc. Invalid configurations will not cause crashes.
Rich Result Objects
Methods that return RollResult, SessionResult, OpposedResult, and ProbabilityResult objects provide comprehensive metadata. Use the GetFormattedResult() methods for display-ready strings.