Custom 3D Dice Pack Developer Guide
JSON Structure Overview
Your dice pack consists of: - {PackName}.json - Main configuration file - {PackName}/ - Folder containing all assets (models, textures, icons, sounds)
Download Example ZIP for Custom Dice
Core Concepts
Dice Positions 0-6 (Core Dice Set)
Positions 0-6 are reserved for the standard polyhedral dice:
| Position | Die Type | Required |
|---|---|---|
| 0 | d4 | Yes |
| 1 | d6 | Yes |
| 2 | d8 | Yes |
| 3 | d10 | Yes |
| 4 | d12 | Yes |
| 5 | d20 | Yes |
| 6 | d10x10 (percentile tens) | Yes |
To override core dice with custom visuals:
{
"position": 1,
"model": "Models/d6_custom.glb",
"map": ["MyPack/custom_d6_texture.png"],
"faces": [
{ "normal": [1.0, 0.0, 0.0], "number": 6 },
...
]
}
Variant Dice (Position 7+)
Add custom dice variants by omitting position or using position >= 7:
{
"id": "weather_storm",
"displayName": "Storm Die",
"baseType": "d6",
"position": 7,
"model": "Models/d6_low.glb", // Reuse existing model
"map": ["MyPack/storm_texture.png"], // Custom texture
"icon": "icons/storm_icon.png",
"faces": [
{ "normal": [1.0, 0.0, 0.0], "number": 1, "label": "Thunder" },
{ "normal": [0.0, 1.0, 0.0], "number": 2, "label": "Rain" },
...
]
}
Face Labels vs Numbers
Each face supports both numeric values and text labels:
{
"faces": [
{ "normal": [...], "number": 5 }, // Shows "5"
{ "normal": [...], "number": 1, "label": "Critical!" }, // Shows "Critical!"
{ "normal": [...], "label": "Banana" } // Shows "Banana" (number defaults to 0)
]
}
Display Priority:
- If label exists → display label
- If no label → display number
- If neither provided → number defaults to 0
Example: Story Dice
{
"id": "story_die",
"displayName": "Story Die",
"baseType": "d6",
"faces": [
{ "normal": [1.0, 0.0, 0.0], "label": "🍌 Banana" },
{ "normal": [0.0, 1.0, 0.0], "label": "🦆 Duck" },
{ "normal": [-1.0, 0.0, 0.0], "label": "🌟 Star" },
{ "normal": [0.0, -1.0, 0.0], "label": "🏰 Castle" },
{ "normal": [0.0, 0.0, 1.0], "label": "🐱 Cat" },
{ "normal": [0.0, 0.0, -1.0], "label": "🌈 Rainbow" }
]
}
Variant-Only Packs
If your pack only contains variants (no core dice set):
{
"displayName": "Weather Dice Collection",
"variantOnly": true,
"dice": [
{
"id": "storm",
"displayName": "Storm Die",
"baseType": "d6",
"model": "Models/d6_low.glb",
"map": ["Weather/storm.png"],
"faces": [...]
},
{
"id": "sunny",
"displayName": "Sunny Die",
"baseType": "d8",
"model": "Models/d8_low.glb",
"map": ["Weather/sunny.png"],
"faces": [...]
}
]
}
Note: With "variantOnly": true, users can only load your pack as additional dice on top of another complete dice set.
Reserved System IDs
Do not use these IDs for custom dice (they're hardcoded for specific game systems):
FATE Dice
dF- FATE die (d6 with -1, 0, +1 results)
Genesys/Star Wars Narrative Dice
nDa- Ability die (d8)nDb- Boost die (d6)nDc- Challenge die (d12)nDd- Difficulty die (d8)nDs- Setback die (d6)nDp- Proficiency die (d12)
If you create custom versions of these dice, use the same IDs so the system recognizes them:
{
"id": "dF", // System will recognize this as FATE dice
"displayName": "Fate Die (Custom)",
"baseType": "d6",
"faces": [
{ "normal": [...], "number": 1 }, // +
{ "normal": [...], "number": 0 }, // blank
{ "normal": [...], "number": -1 } // -
]
}
Display Names
- Pack-level
displayName: Shown in dice pack selection UI - Die-level
displayName: Shown in tooltips and roll results
{
"displayName": "Mystical Runes (by YourName)", // Pack name
"dice": [
{
"position": 1,
"displayName": "Runic d6", // Die name (optional, defaults to "d6")
...
},
{
"id": "oracle_die",
"displayName": "Oracle's Vision", // Important for variant dice
...
}
]
}
For d10x10 (percentile): The UI automatically displays it as "d100" to users.
Quick Examples
Full Pack (Reskinned Core + Variants)
{
"displayName": "Dragon Scales",
"dice": [
{ "position": 0, "model": "Models/d4_low.glb", "map": ["Dragon/d4.png"], ... },
{ "position": 1, "model": "Models/d6_low.glb", "map": ["Dragon/d6.png"], ... },
...
{ "position": 6, "model": "Models/d10_low.glb", "map": ["Dragon/d100.png"], ... },
{ "id": "dragon_breath", "displayName": "Dragon's Breath", "position": 7, ... }
]
}
Variant-Only Pack
{
"displayName": "Elemental Symbols",
"variantOnly": true,
"dice": [
{ "id": "fire", "displayName": "Fire", "baseType": "d6", ... },
{ "id": "water", "displayName": "Water", "baseType": "d6", ... },
{ "id": "earth", "displayName": "Earth", "baseType": "d8", ... },
{ "id": "air", "displayName": "Air", "baseType": "d8", ... }
]
}
Story Dice with Labels
{
"displayName": "Adventure Dice",
"variantOnly": true,
"dice": [
{
"id": "quest_die",
"displayName": "Quest Die",
"baseType": "d6",
"model": "Models/d6_low.glb",
"map": ["Quest/symbols.png"],
"faces": [
{ "normal": [1.0, 0.0, 0.0], "label": "Treasure" },
{ "normal": [0.0, 1.0, 0.0], "label": "Monster" },
{ "normal": [-1.0, 0.0, 0.0], "label": "Trap" },
{ "normal": [0.0, -1.0, 0.0], "label": "Ally" },
{ "normal": [0.0, 0.0, 1.0], "label": "Magic" },
{ "normal": [0.0, 0.0, -1.0], "label": "Rest" }
]
}
]
}
Tips
- Reuse models: Point to existing models like
"Models/d6_low.glb"and just change textures - Test with simple packs first: Start with one variant die before creating a full set
- Icon paths: Provide custom icons for better UI:
"icon": "icons/my_die.png" - Additive packs work together: Users can enable multiple variant packs simultaneously