Simple C# coding error but unsure how to fix.

Hi everyone. I was hoping someone can help me figure out what I’m doing wrong here. I’m sure its a simple fix just not sure what to do.

Here’s my code using System.Collections;using System.Collections.Generic;using UnityEngine; - Pastebin.com

I get the compiler error: Assets/StoryTeller.cs(14,20): error CS0052: Inconsistent accessibility: field type StoryTeller.character.locations' is less accessible than field StoryTeller.character.loc’

Your enum is private, but you have accessed it with a public variable.

Thanks! Perhaps I don’t quite understand when to use private vs public variables. I changed that but now I have another error. Here’s the full code.

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

public class StoryTeller : MonoBehaviour {

    public Text descriptor;

    public enum locations {intro_1, intro_2, intro_3};

    public class character
    {
        public locations loc;  
    }
    public character player = new character();
    // Use this for initialization
    void Start ()
    {
        player.loc = locations.intro_1;
    }
  
    // Update is called once per frame
    void Update ()
    {
        switch (player.loc)
        {
            case locations.intro_1:
                descriptor.text =     "You are formless. You drift through the deep sea of thoughts. You are in a realm of proto-thoughts. They " +
                                    "rise out of the pure consciousfields that permeates all there is. They're newborn thoughts. In a realm " +
                                    "ancient and immeasurable by time, contless eons will pass before these thought forms mature and reach the " +
                                    "the conscious minds of living beings.";
                break;
            case locations.intro_2:
                descriptor.text = "test";
                break;
            case locations.intro_3:
                descriptor.text = "test";
                break;  
        }
    }
}

With this code I get this error while it runs:
NullReferenceException: Object reference not set to an instance of an object
StoryTeller.Update () (at Assets/StoryTeller.cs:29)

Thanks for the help by the way, really appreciate it.

Your problem here is that you are trying to access the “text” component but you aren’t telling Unity where to get the component from. Unity is component based which means that you need to let Unity know which compoenent you are referring to, if the text component is on the same object as your script then you could do this inside you start method:

GetComponent<Text>();

This line of code will get the text component from the same object the script is attached to, if the text is on a different object then you can use a tag to find that object and get the text component.

I hope this helps

-Joshmond

1 Like

ohhhh! I didn’t drag the text ui object to the ‘Descriptor’ field in the script component. Now it works great! Could anyone elaborate a bit more on when to use public vs private? Thanks for all the help!

Another thing to note is that you do not need the class “character”. To shorten your code a little you could just do this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
    public class StoryTeller : MonoBehaviour
    {
 
        public Text descriptor;
        public Locations location;
        // Use this for initialization
        void Start ()
        {
            GetComponent<Text>();
             location = Location.NONE; // default value
        }
 
        // Update is called once per frame
        void Update ()
        {
            switch (location)
            {
                case Locations.INTRO1:
                    descriptor.text =     "You are formless. You drift through the deep sea of thoughts. You are in a realm of proto-thoughts. They " +
                                        "rise out of the pure consciousfields that permeates all there is. They're newborn thoughts. In a realm " +
                                        "ancient and immeasurable by time, contless eons will pass before these thought forms mature and reach the " +
                                        "the conscious minds of living beings.";
                    break;
                case Locations.INTRO2:
                    descriptor.text = "test";
                    break;
                case Locations.INTRO3:
                    descriptor.text = "test";
                    break;
            }
        }
    }


  public enum Locations
  {
     NONE,
     INTRO1,
     INTRO2,
     INTRO3
  }

This is on/off topic… You might want to consider writing to your text property only when needed (like, if it changes, or you’re showing it the first time, etc…).
Say, your character enters the area, you want to show them some text… great, that’s a good time.
However, if they’re in the area for any amount of time, and you’re running this update loop to set the text property over and over and over and over (every frame) :slight_smile:

1 Like

As a rule of thumb you should never use “public” variables as a programmer, what this does is make all data/members available to everything and allows you to modify it’s value from anywhere, this is bad practice. Once you start learning more about Object-Oriented Programming you will learn about something called “Encapsulation” which is essentially hiding variables but you expose them them using methods, this means you are modifying values but not directly, instead you are using a layer of abstraction to do so (methods). I will give you two different ways of doing this in C#, one is more long-winded and the other is a shorter version

//Example One

public class Vehicle
{
    private float _engineSize = 1.2; // This variable is not accessible to other classes/objects
  
   public float GetEngineSize()
   {
       return _engineSize; // allows us to call this method to return to value of the "_engineSize" variable
   }

 
   public float SetEngineSize(float engineSize)
   {
        _engineSize = engineSize; // allows us to call this method to set to value of the "_engineSize" variable
   }
}

Notice that we are using methods to get and set the values but we cannot access the vatiable and change its contents directly. This approach will work in C# but it is mainly used in an older OOP language called “Java”. C# provides a much more convenient way which is this:

//Example Two

public class Vehicle
{
    public float EngineSize {get; set;}
}

This code does exactly the same as the code above but it’s a little more concise.

In Unity we use the “public” modifier to serialise that variable to the inspector but there is another way we can do this and it’s with the “[SerializeField]” and it looks like this:

public class Vehicle
{
    [SerializeField]
    private float _engineSize; // This gets shown in the inspector;

  // Now we can crate a property and refer to that is we need to pass any information around

  public float EngineSize
  {
     get {return _engineSize;}
     set {_engineSize = value;} // Allows us to assign a value from other classes/objects that need to access/change this data
  }

}

I hope this post was helpful, it is a bit of an advanced topic but this is the gist of how public and private variables work. As a general rule, avoid using public variables if you can.

-Joshmond

Thanks for the tips everyone

Ya you’re right there are definitely problems with the way I am coding. Here’s my code now…

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

public class StoryTeller : MonoBehaviour {

    // Character Enumerations
    public enum locations {intro_1, intro_2, intro_3};
    public enum socialCaste{not_set, royalty, serf, slave};

    public Text descriptor;

    public character player = new character();

    public class character
    {
        public locations loc;
        public socialCaste caste;   
    }
    // Use this for initialization
    void Start ()
    {
        player.loc = locations.intro_1;
        player.caste = socialCaste.not_set;
    }
   
    // Update is called once per frame
    void Update ()
    {
        switch (player.loc)
        {
            case locations.intro_1:
                descriptor.text =     "You are formless. You drift through the deep sea of thoughts. You are in a realm of nearly infinite proto-thoughts. They " +
                                    "rise out of the pure conscious field that permeates all there is. They're newborn thoughts. In a realm " +
                                    "ancient and immeasurable by time, contless eons will pass before these thought forms mature and reach the " +
                                    "the conscious minds of living beings.\n\n" +
                                    "One of these proto-thoughts drifts by...";
               
                    descriptor.text +=     "\n\nThis thought is destined to rise up through the sea and enter the material world through " +
                                        "the mind of a human who is of royal blood.\n\n" +
                                        "(F)ollow this thought form or allow it to pass and (D)rift among the others.";
                    if (Input.GetKeyDown(KeyCode.F)) player.caste = socialCaste.royalty;
                    else if (Input.GetKeyDown(KeyCode.D))
                    {
                        descriptor.text =     "You drift for a while in the birthplace of all human thoughts. They flow around you like bubbles in sea foam. " +
                                            "You encounter another newly created thought form. This one is destined to manifest in the mind of a serf.\n\n" +
                                            "(F)ollow this thought form or allow it to pass and (D)rift among the others.";
                        if (Input.GetKeyDown(KeyCode.F))
                            player.caste = socialCaste.serf;
                        else if (Input.GetKeyDown(KeyCode.D))
                        {
                            descriptor.text =     "Floating a while longer you happen upon yet another thought form destined for the mind of a slave.\n\n" +
                                                "(F)ollow this thought form or allow it to pass and (D)rift among the others.";
                            if (Input.GetKeyDown(KeyCode.F))
                                player.caste = socialCaste.slave;
                        }
                    }
                break;
            case locations.intro_2:
                descriptor.text = "test";
                break;
            case locations.intro_3:
                descriptor.text = "test";
                break;   
        }
    }
}

Right now I’m having a problem (I think) with the text being reset after keys are pressed. So, ya probably not the best idea to be setting the text inside the update function. But now I’m not really 100% sure how I should go about asking the user for input, changing text and variable, rinse repeat.

Thanks for the info. Some of it is a little bit above me right now but I get the concept. I’m taking a Udemy course on c# and unity right now… but I wonder a bit if its glossing over proper C# programming too much.