Character creator connundrums

…so I’m trying to implement a character creator as a stand-alone game (a project to wrap my head around Unity basics). The problem is: I’m instantiating scriptable objects to represent the different species a player can select from, but the stats I have in the scriptable objects aren’t tallying with the base scores. I’ve created a switch statement that’s attached to the buttons with Debug logging:

namespace Rep
{
    public class SpeciesScores : MonoBehaviour
    {
        public int buttonID;
       
        public Pteryx pteryx;
        public HaamanRykul haamanRykul;
        public Human human;
        public Fae fae;
        public Doargedran doargedran;
        public Marsupian marsupian;
        public Savuin savuin;
        public Folk folk;
        public Species species;
        public void GetSpecies()
        {
            switch(buttonID)
            {
                case 1:
                   
                    pteryx = ScriptableObject.CreateInstance<Pteryx>();
                    Debug.Log("I found a Pteryx egg!");
                   
                    break;
                case 2:
                   
                    haamanRykul = ScriptableObject.CreateInstance<HaamanRykul>();                   
                    Debug.Log("I found an Haaman embryo!");
                   
                    break;
                case 3:
                   
                    human = ScriptableObject.CreateInstance<Human>();
                    Debug.Log("I found a Human baby!");
                   
                    break;
                case 4:
                   
                    fae = ScriptableObject.CreateInstance<Fae>();
                    Debug.Log("I found a Fae spawn!");
                   
                    break;
                case 5:
                   
                    doargedran = ScriptableObject.CreateInstance<Doargedran>();
                    Debug.Log("I found a Doargedran baby!");
                   
                    break;
                case 6:
                   
                    marsupian = ScriptableObject.CreateInstance<Marsupian>();
                    Debug.Log("I found a Marsupian embryo!");
                   
                    break;
                case 7:
                   
                    savuin = ScriptableObject.CreateInstance<Savuin>();
                    Debug.Log("I found a Savuin spawn!");
                   
                    break;
                case 8:
                   
                    folk = ScriptableObject.CreateInstance<Folk>();
                    Debug.Log("I found a Folk grommet!");
                   
                    break;
                default:
                    species = null;
                    break;
              } 
           

        }
       
               
    }
}

…and I have one of the stat scripts calling this method:

namespace Rep
{
    public class Ambition : MonoBehaviour
    {
        SpeciesScores speciesScores;
        public float ambition;
        public Text ambitionScore;
        public void Awake()
        {
            ambition = 1;
            ambitionScore.text = ambition.ToString();
           
        }

        public void SpeciesScore(Species species)
        {
            speciesScores = GameObject.FindGameObjectWithTag("SpeciesScores").GetComponent<SpeciesScores>();
            speciesScores.GetSpecies();
            speciesScores.ToString();
        }
    }
}

I’m stumped as to what I’m missing; I get no compile errors and all the tutorials I’ve looked at haven’t amounted to squat - even the Unity Discord servers are getting sick of me :stuck_out_tongue:

Any & all help appreciated - apologies for the code-dump

When you use CreateInstance you get a blank copy of the scriptable object. Use Instantiate to get a copy of an existing scriptable object.

1 Like

my bad; thanks, but nope
I might have to research prefabs a bit more & use them instead - cheers for the input tho

Wow, character creators are one of the trickiest things, right up there alongside an inventory. Are you sure you want to even consider tackling this before you’ve made a few dozen games??

Here’s my warning about inventories. Almost all of it applies to character creators.

Inventories (and shop systems) are fairly tricky hairy beasts. They contain elements of:

  • a database of items that you can possess
  • a database of the items you actually possess
  • persistence of this information to storage between game runs
  • presentation of the inventory to the user (may have to scale and grow)
  • interaction with items in the inventory
  • interaction with the world to get items in and out
  • dependence on asset definition (images, etc.) for presentation

Just the design choices of an inventory system can have a lot of complicating confounding issues, such as:

  • can you have multiple items? Is there a limit?
  • are those items shown individually or do they stack?
  • are coins / gems stacked but other stuff isn’t stacked?
  • do items have detailed data shown (durability, rarity, damage, etc.)?
  • can users combine items to make new items?
  • can users substantially modify items with other things like spells, gems, etc.?
  • does a worn-out item (shovel) become something else (like a stick) when the item wears out?
  • etc.

Your best bet is probably to write down exactly what you want feature-wise. It may be useful to get very familiar with an existing game so you have an actual example of each feature in action.

Once you have decided a baseline design, fully work through two or three different inventory tutorials on Youtube, perhaps even for the game example you have chosen above.

Or… do like I like to do: just jump in and make it up as you go. It is SOFT-ware after all… evolve it as you go! :slight_smile:

Breaking down a large problem such as inventory:

https://discussions.unity.com/t/826141/4

“Combining a bunch of stuff into one line always feels satisfying, but it’s always a PITA to debug.” - Star Manta on the Unity3D forums

That’s not how engineering works.

You need to find out what (if anything) the above code is doing.

Then you need to reason how that code differs from what you expect.

You must find a way to get the information you need in order to reason about what the problem is.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

yeah, I’m fast learning that it ain’t so simple
I was right in that a species needs to be a SO, but I still can’t get the scores associated to register
“This might take me a really long time.” - Tank-Girl
Thanks for the input, Kurt - I’m kinda stubborn in that I’ve jumped right in (I’ve been sitting on this system for near 25 years now) & I’ll putter along until either my heart or head gives out, or I stumble across that ol’ Rosey Key :stuck_out_tongue:

YES! DO IT! I would… I appreciate that attitude!

But be prepared to toss stuff out and do it again when you learn how to do it better.

It is incredibly liberating to get rid of your first (or third) draft and then make the next one… correctly!!

Be sure to use source control so you can reason about changes over time, as well as revert damage or mistakes easily.

Here’s my source code blurb:

Please consider using proper industrial-grade source control in order to guard and protect your hard-earned work.

Personally I use git (completely outside of Unity) because it is free and there are tons of tutorials out there to help you set it up as well as free places to host your repo (BitBucket, Github, Gitlab, etc.).

You can also push git repositories to other drives: thumb drives, USB drives, network drives, etc., effectively putting a complete copy of the repository there.

As far as configuring Unity to play nice with git, keep this in mind:

https://discussions.unity.com/t/736093/3

Here’s how I use git in one of my games, Jetpack Kurt:

https://discussions.unity.com/t/807568/3

Using fine-grained source control as you work to refine your engineering:

https://discussions.unity.com/t/826718/2

Share/Sharing source code between projects:

https://discussions.unity.com/t/719810/2

Setting up an appropriate .gitignore file for Unity3D:

https://discussions.unity.com/t/834885/5

Generally setting Unity up (includes above .gitignore concepts):

https://thoughtbot.com/blog/how-to-git-with-unity

It is only simple economics that you must expend as much effort into backing it up as you feel the work is worth in the first place.

“Use source control or you will be really sad sooner or later.” - StarManta on the Unity3D forum boards

I 'precieate the appreciation (I can be ever so stubborn about putting too much on my plate) XD
I’ll wade through all your links (ta for them) over the next couple of weeks in between on-line searches & other tutorial catch-ups; I’m sure they will turn out to be invaluable. As of now the whole coding project is bare-bones, (I’ve restarted a couple of times already) but it’d be nice to get it to a point where I can implement it into a wider framework. And of not, at least my heart (or my head) will have finally given out & I can get a little peace :stuck_out_tongue:

1 Like

So I’ve changed the code to use instantiate, but now I get a ‘local variable unassigned’ error & I’ve got no idea how to rectify it; I thought the declaration of public Species pteryx; would have been sufficient, but apparently because that’s outside the switch statement it just doesn’t compute. I’ve tried several variations on the instantiate to no effect - how would I go about initializing ‘(pteryx)’ so that it at least compiles?

public void GetSpecies()
        {
            switch(buttonID)
            {
                case 1:
                  
                    Species pteryx = Instantiate(pteryx); //unassigned local variable
                    Debug.Log("I found a Pteryx egg!");
                  
                    break;

Kinda just thinking out loud on this, but to be honest, it’s busting my balls XD

This line:

Species pteryx = Instantiate(pteryx);

Is a new unassigned reference that you’re trying to instantiate into itself. Ergo, trying to duplicate nothing, so of course it’s going to throw an error.

You need to assign something into your public field, then duplicate it into a new reference.

For example:

namespace Rep
{
    public class SpeciesScores : MonoBehaviour
    {
        public int buttonID;
     
        public Pteryx pteryx; //assign your scriptable object to this in the inspector

        public void GetSpecies()
        {
            switch(buttonID)
            {
                case 1:
                 
                    Pteryx pteryxInstance = Instantiate(pteryx); //make a copy into a new reference rather than replacing the existing instance
                    Debug.Log("I found a Pteryx egg!");
                    break;
              }         
        }
    }
}

I don’t understand what you mean by this, but I tried with no dice - I just get "unnecessary assignment of a value to ‘pteryxInstance’ "
Thanks for playing, tho

Well yeah, if you don’t do anything with the new field then your IDE will likely warn you about it. It’s just a warning, nor an error. I’m just showing you the correct way to duplicate scriptable objects.

sorry, but something about this just smells fishy to me - I think it’s unnecessarily spaghettifying code…

So I’ve back-tracked a bit & got it to a point where I’m selecting buttons & getting the Debug logging, and I’ve noticed in the inspector that a clone of the scriptable object is definitely being generated, but still no dice on getting the clone to tally its scores with the base scores, or even just replace them. I’ll be using this thread as a blog for how things are going for me; developments to follow (hopefully)…

No, Pteryx can be treated as a Species, or as a Scriptable Object, or as a UnityEngine.Object. A type derived from another type can be treated as if it were any of its parent types. That’s how inheritance/polymorphism works.

Edit: Thanks for editing your post out from under me.

1 Like

my bad; I’m kinda (and no kinda about it) learning on the fly, and my scripting endeavours rely heavily on experimentation. You’re welcome :wink:
In your defence, you were mostly right about the instantiation - the specifics of the cast were a little off, tho:

case 1:
                   
                    pteryx = (Pteryx)ScriptableObject.CreateInstance(typeof(Pteryx));
                    Debug.Log("I found a Pteryx egg!");
                   
                    break;

I found this cast on a scriptable objects video by samyam - I’m not sure if its helpful to me right now though, as I still can’t get the stats to relay… ah, well, maybe next life…

Nearly two years later & HA

AHA
minor progress - using chatGPT as a springboard I can now select a species from a button & have the feature scores update accordingly. Hopefully I can figure out how to limit the score update to one species alone
Then I can start working on (gulp) getting clan selections to do the same…

…and it’s gone
I’d decide I don’t care anymore, but it’s really pissing me off - time to start over (again again)

So it looks like periodically scrapping my work & starting over has its benefits - I’m now roughly halfway through the reboot & testing is proving to have acceptable results. Just gotta finish the prototype & then I’ll be ready to scrap it all & start again (again)…

I haven’t even needed chat GPT XD

1 Like

…it’s a little over two years ago that I started this thread as a means of tracking my progress, and I’ve been sorely lax in tracking my progress…
Nevertheless, I have a complete stage 1 of my character creator: the assignment of selectables that impact a representative’s features is complete and I’m now focusing my attention on the acquisition of competencies & specialisations. I’ve run into a knot in my structure where I need to access a representative’s ‘modifier scores’ to correctly assign a score (based on the average of two features) to the specialisation in question. The method I’ve generated to divine which two features to reference when calculating a specialisation’s score is as concise as can be, but because it needs to reference the representative object in order to calculate the score I’m stuck in null-town; I can’t figure out how to properly reference the representative without also referencing the game object it’s all attached to (let alone figure out how to make the game object reference ‘not-null’), so I’m currently stuck screaming-into-the-void. I’ve kind-of exhausted the run of tutorial videos on You-tube, so it looks like I’ll be taking an extended break while I struggle with this.
Update concludes in 5… 4… 3… 2… 1…

I mean if you’re having particular problems, perhaps make a thread describing the problem to see if you can get some advice?

In any case, what I’ve found making my own customizable character system (in this case, a customisable robot player character), is that a separating your model and view is pretty useful, if not crucial. By which I mean having some pure data representation of your customisable… whatever, and then use that to build your game object/scene representation.

It’s more upfront work, but you can structure your data in a way that makes the most sense for your particular situation, rather than being shackled to the transform heirarchy (which is useful for some things, but also not useful for plenty others). It also means you have a high chance of all this data being safe to serialize without any extra work.