Character Generator

@Rob you said you have played Dungeons and Dragons and other d20 games. The game I am trying to build is an online version of the table top game, but not an MMORPG. With all the stats, skills, feats and multipliers and even the combat style so it will be a turn based game. I would like for it to be that 4 or 5 players can run a campaign together or you can pop in and out of parties to play with other players of the same level. The main problem that I am having right now is the character creation part. i can’t find any courses on how to set up a system like D&D.

Hi Michael,

Yes, many years ago I did the Dungens & Dragons / Fighting Fantasy / Warhammer / Warhammer 40k thing, was good fun.

Setting up a system like D&D would be a fairly large project, if it were me, before even looking at Unity or any code I would think about breaking that project down in to many smaller pieces. You could either use pen and paper or a solution like Trello or similar to document the features, and then the component parts of those features.

Even Character Creation is a fairly large topic, so I would break that down in to small component parts as well. For example, you’ll need perhaps a class to represent the character, possibly, but not necessarily classes to represent the stats (intelligence, strength, dexterity etc). Consideration for how these will be populated, will the player be given a set of “points” to spend but with rules around them, e.g. “no more than 5 points can be spent on strength at the start”, or would you prefer a more, seemingly, random approach where dice rolls occur. If dice rolls, you then need to consider which type of dice, D6, D4, D8, D10 etc.

As you can see, just the character creation aspect of this as a project has grown and generated quite a few thoughts just in the paragraph above. My recommendation would be to really write this out and start to work through the ideas and potential problems before getting too involved in the code side of things.

When you do start with the code, I would also recommend keeping it simple. So for example, I recall D&D had about 8 characteristics (roughly), Warhammer had about 6 I think, try to create your character creation system so that the number of characteristics doesn’t actually matter. e.g. you begin with one, test it through, if it works, you should be able to just increase this easily by adding some additional characteristic to a config which can be read in. If you create a character class with 8 characteristics from the beginning, all requiring different dice rolls and interactions I can almost guarantee it will become so complicated from the outset that it will become messy, hard to read/understand code, and as soon as you turn your back on it for a few days to do other things, when you return it won’t make any sense to you anymore. :slight_smile:

Nutshell, break down project into features, break down features into a series of small parts, start small, keep it simple.

Hope the above is of use :slight_smile:


Updated Thu May 03 2018 16:17

I meant to add, I was helping another student in the past with the concept of dice rolling, the code I put together for that is available here if you want it / want to look at it;

it dose help and i was thinking about letting the player choose if they want to do a point buy or dice roll for the stats. This is what i have right now i placed 10 in the stats as a place holder also the 100 hp . But on my player i can’t pick what class the player is.

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

public class Player: MonoBehaviour
{
    [SerializeField] float maxHealthPoints = 100f;

    float currentHealthPoints = 100f;

    public float healthAsPercentage
    {
        get
        {
            return currentHealthPoints / maxHealthPoints;
        }
    }
    public int Strength = 10;
    public int Dexterity = 10;
    public int Intelligence = 10;
    public int Constitution = 10;
    public int Wisdom = 10;
    public int Charisma = 10;
    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
    public void InitStatsForPlayerClass(PlayerClasses type)
    {
        switch (type)
        {
            case PlayerClasses.Barbarian:
                SetDefaulitStatsForBarbarian();
                break;
            case PlayerClasses.Bard:
                SetDefaulitStatsForBard();
                break;
            case PlayerClasses.Cleric:
                SetDefaulitStatsForCleric();
                break;
            case PlayerClasses.Druid:
                SetDefaulitStatsForDruid();
                break;
            case PlayerClasses.Fighter:
                SetDefaulitStatsForFighter();
                break;
            case PlayerClasses.Monk:
                SetDefaulitStatsForMonk();
                break;
            case PlayerClasses.Paladin:
                SetDefaulitStatsForPaladin();
                break;
            case PlayerClasses.Ranger:
                SetDefaulitStatsForRanger();
                break;
            case PlayerClasses.Rouge:
                SetDefaulitStatsForRouge();
                break;
            case PlayerClasses.Sorcerer:
                SetDefaulitStatsForSorcerer();
                break;
            case PlayerClasses.Wizard:
                SetDefaulitStatsForWizard();
                break;
            default:
                break;
        }

    }
    public void SetDefaulitStatsForBarbarian()
    {
    }
    public void SetDefaulitStatsForBard()
    {
    }
    public void SetDefaulitStatsForCleric()
    {
    }
    public void SetDefaulitStatsForDruid()
    {
    }
    public void SetDefaulitStatsForFighter()
    {
    }
    public void SetDefaulitStatsForMonk()
    {
    }
    public void SetDefaulitStatsForPaladin()
    {
    }
    public void SetDefaulitStatsForRanger()
    {
    }
    public void SetDefaulitStatsForRouge()
    {
    }
    public void SetDefaulitStatsForSorcerer()
    {
    }
    public void SetDefaulitStatsForWizard()
    {
    }
}

Appreciating this is a work in progress at the moment, but you would probably want to have the actual player not have all of the character creation code in it. Think of the player as just a container for the data that is relevant to it. So, for example, your character creation process instantiates a new player object with the relevant values.

With regards to picking the character class, you could consider an enum initially, although again, you may want to consider specific classes later on.

using UnityEngine;

public class CharacterCreator : MonoBehaviour {

	private enum CharacterClass { Barbarian, Bard, Cleric, Druid, Fighter, Monk, Paladin, Ranger, Rogue, Sorcerer, Warlock, Wizard };
	
	[Header("Class Type")]
	
	[SerializeField]
	[Tooltip("Select the class of character")]
	private CharacterClass characterClass;
	
	[Space(10)]
	
	[Header("Attributes")]
	
	
	[Tooltip("Strength: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int strength = 10;
	
	[Tooltip("Dexterity: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int dexterity = 10;
	
	[Tooltip("Intelligence: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int intelligence = 10;
	
	[Tooltip("Constitution: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int constitution = 10;
	
	[Tooltip("Wisdom: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int wisdom = 10;
	
	[Tooltip("Charisma: A value between 1 and 20")]
	[RangeAttribute(1, 20)]
	[SerializeField]
	private int charisma = 10;
	
}

image

image

Thank you so much that helped a lot now just have to figure out how to use the dice roller lol.

1 Like

I think you need to be clear on the perspective here. For example, with what I posted above, it would be the “designer” using Unity that would be creating a character. Do you want the actual “player” to be able to create their character?

If you want to provide just randomly generated characters then the “dice” mechanic is fairly straight forward, just iterate through each of your attributes and get a random value between 1 and 20. Job done.

If you want the player to be able to create their character then you need to move this interface into a scene. Again, it doesn’t have to be an actual 3D dice that they see on the screen, you could just have a button next to each attribute that says “Roll 1D20”, they click on it and are given a value, the button is then disabled (so they can’t cheat). The act of clicking on the button would run a method that produces the random value between 1 and 20.

Make sense?

I would like for the player to be able to roll their stats which would be 4d6 drop the lowest, and let them place the stats where they think they should go. For ex. if i was a wizard and i rolled on 18 for my Str. I would want that in my Wis. and not my Str. I don’t know if there is a way to keep track of what they roll and let them place the stats that way they can’t just say they rolled all 18.

Yeah you could achieve that. Perhaps you would take them through the process of rolling a set of dice for the number of attributes in question, store each total in an array, display each total in the scene. Potentially you could then use maybe drag/drop to let them slide the total they wanted to the appropriate attribute.

Just in the above though that’s a lot of features.

Sounds like it. Are there any courses that go over that I’m still new to all of this only a month in.

You may find some by searching the web but you are perhaps unlikely to find one that delivers exactly what you want. I suspect you will gain a better understanding and knowledge by simply having a go yourself, but like my original reply suggested, start small. Log all the features you want to have but identify what would be the minimum viable product.

In the above example for the character creation, you could just have one button that generated random values between 1-20 and populate the stats for the player and then - boom - off you go with the next feature. You now have a player character that has stats which can influence decisions/interactions within the world you create. That is not to say to lose sight of the desire to create the more enhanced version, but add a little more to each area as you progress with your own learning and experience. You could of course find a middle ground, perhaps you have a button next to each attribute which generates the random value but you let them click on it as many times as they want. If you want to be a wizard and didn’t get 18 for Wisdom, you just click it again until you get a higher result. That doesn’t have to be how it stays indefinitely, but it gives you the ability to progress with other areas of your game.

By succeeding with multiple small features you will maintain a really high morale and enthusiasm for your project as opposed to getting so bogged down because you can’t, for example, find a way to drag/down values into specific attributes.

I would be keen to see how you develop your idea and project as your progress, so if you are happy to, do keep sharing with us :slight_smile:

Will do thank you for all the help.

1 Like

You’re more than welcome :slight_smile:

@Rob you said “If you want the player to be able to create their character then you need to move this interface into a scene. Again, it doesn’t have to be an actual 3D dice that they see on the screen, you could just have a button next to each attribute that says “Roll 1D20”, they click on it and are given a value, the button is then disabled (so they can’t cheat). The act of clicking on the button would run a method that produces the random value between 1 and 20.” I have been trying to do this but I’m not sure how to.

Hi Michael,

Ok, so let’s break it down, start small and build it up.

Can you create a new scene, and pop a canvas in it and add a single button (it doesn’t have to look great)

Now create a new script, example.cs, and add this code;

using UnityEngine;

public class Example : MonoBehaviour
{
    public void DisplayMessage()
    {
        Debug.Log("Hello Michael!");
    }
}

Create a new GameObject in the scene, attach the Example.cs script to it.

For the button, look at the On Click event handle in the Inspector, drag your GameObject (with the example.cs script attached) to the Object property, and then select the DisplayMessage method for the function dropdown.

Run the game.

When you click the button you should see a message appear in the console.

Let me know when you have this part up and running and we can move forward.

Okay I got that.

1 Like

Great…

So, you have the interaction of the button in place now, we can just change what is happening when it is pressed.

Now, if you grab that Dice script from the GitHub repository I gave you the link for before, you can add that script to the project also - just the Dice.cs script, don’t worry about the Example.cs script that is with it.

Now, in your example.cs script, create the following method;

public void RollForAttribute()
{
        // Usage example - single die
        Debug.Log(Dice.RollDie(Dice.DieType.D20));
}

…and in the On Click event handler of the Button, change the function dropdown to RollForAttribute instead of DisplayMessage.

Run the game.

You should now see random values appear in the console each time you click the button, values that can come from a D20.

Get that

Working?

yes sir, just need to have them drop the lowest dice and add up

Ok, so on the GitHub respository, if you look at the Example.cs script you’ll see that you can roll multiple dice, of a specific type, and return them as an int array, ordered by your choice (ascending/descending).

So… have a go at using that example to return a number of D20s to be rolled, ordered with the lowest value last.

Then, apply a little logic in the method above so that you take on the first, however many dice, you are interested in - thus, the last is ignored.

So, as an example, if you are allowed to roll 3D20, and ignore the lowest, then get the results of 3D20s, ordered accordingly, and then take the int array that is returned and grab just the first two values you require, add them up and perhaps pop the total out to the console, just so you can actually see it.

Have a go at this bit yourself, if you get stuck, let me know. I’ll be AFK for about half an hour but back after that for a while.


Updated Sat May 05 2018 22:43

How’s it going @Michael_W_Davis

Privacy & Terms