Search Unity

c# not finding a solution to differentiate outputs from my scripts

Discussion in 'Scripting' started by FeniceArcana2, Jul 1, 2018.

  1. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8
    Hello, i'm pretty new to Unity and not a real expert on C# so maybe i'm missing something here.
    I'd like to create a simple simulator made of a few different scripts. I Already created the core of it but cant get to resolve the principal issue:
    1) i have some game object with a scipt attached [products] and after some time, this product would like to check if i have enought ingredients of some type to "Bake" the product.
    2) i have some ingredients that gather during real time [time.deltatime]
    problem is , i'm using just one script for all ingredients and one for all products, so in fact when the ingredient get its own ++, it's just a number. i dont know how to differentiate all theyr output to have, just as an example, one ingredient output as Flour and another as Sugar.
    I figured how can i do it creating a script for each single ingredient and later for each product but it seems just soooo wrong.
    Maybe i can use lists and array to do it but i'm italian and really am having a hard time to figure how to use Lists and array. So for now, unless i have some example script, i cant just grasp how to solve it.

    Thanks to anyone who could give me some int [also only some good tutorial to figure out how to use Lists]



    just to show a bit of it... i have this slider function... the slider go max and output a " productUnits++;" of this product...but since the script it s the same for oll product, i dont get different ingredients. thats what i need to change.



    if (startTimer || (faerieAtWork >= 0))
    {
    currentTimer = currentTimer + Time.deltaTime * faerieAtWork;
    progressSlider.value = currentTimer / storeTimer;
    if (currentTimer > storeTimer)
    {
    startTimer = false;
    productUnits++;

    progressSlider.value = 0;
    currentTimer = 0;
    productUnitsText.text = productUnits.ToString();
    }
    if (storeTimer <= 0)
    {
    progressSlider.value = 1;
    productUnitsText.text = productUnits.ToString();
    }
    }
    else { progressSlider.value = 0; }
    productUnitsText.text = productUnits.ToString();
     
  2. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Whilst not exactly the same, your problem is sounding similar to the problem of inventory handling. Here is a link to a Unity tutorial covering invemtory handling. It may not be exactly what you want, but may be of interest.

    In terms of List, remember that is a C# language feature and not Unity specific in any way. But here is a Unity tutorial covering the basics of coding in C#. That may prove helpful.

    Also, scroll to the top of the page and click on "Learn". There is lots of good stuff there as well. :)
     
  3. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8

    Thanks for the advice.
    Until now i alwais worked just on visual studio with c# but Lists and Arrays are my weak point. I cant find a good tutorial in my own language so i search english one but...meh... isnt that easy understand with a teacher who cant reply at your questions XD But thanks for the hint, i'll start from those ^_*
     
  4. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    There are many ways of handling a list of things.

    Here is some code you could maybe try. It doesn't use a list or an array (sorry) but the idea is to use Dictionaries to allow for the growing of different ingredients. Note: this is untested, but is it helpful to you? :
    Code (CSharp):
    1. class CIngredient
    2. {
    3.     public bool Grow
    4.         {   get { return m_start; }
    5.             set { m_start = value;
    6.                   m_currentTimer = 0; }
    7.         }
    8.  
    9.     public float Progress { get { return m_currentTimer / m_maxTimer; } }
    10.     public int Units { get { return m_productUnits; } }
    11.  
    12.     public void NextStep()
    13.     {
    14.         if (m_start)
    15.         {
    16.             m_currentTimer += Time.deltaTime;
    17.  
    18.             if (m_currentTimer > m_maxTimer)
    19.             {
    20.                 Grow = false;
    21.                 m_productUnits++;
    22.             }
    23.         }
    24.     }
    25.  
    26.     bool m_start;
    27.     float m_currentTimer, m_maxTimer = 3f;
    28.     int m_productUnits;
    29. }
    30.  
    31.  
    32.  
    33. public class IngredientManager : MonoBehaviour
    34. {
    35.     public enum ingredientTypes { flour, sugar, biscuits, cheese };
    36.  
    37.     public void AttachUI(ingredientTypes ingredient, Slider slider, Text text)
    38.     {
    39.         m_sliders[ingredient] = slider;
    40.         m_text[ingredient] = text;
    41.     }
    42.  
    43.     public void Grow(ingredientTypes grow)
    44.     {
    45.         m_ingredients[grow].Grow = true;
    46.     }
    47.  
    48.     void Start()
    49.     {
    50.         foreach (ingredientTypes ingredientName in Enum.GetValues( typeof( ingredientTypes )))
    51.         {
    52.             m_ingredients.Add(ingredientName, new CIngredient());
    53.         }
    54.     }
    55.  
    56.     void Update()
    57.     {
    58.         foreach (var ingredient in m_ingredients)
    59.         {
    60.             ingredient.Value.NextStep();
    61.  
    62.             if (m_sliders.ContainsKey(ingredient.Key))
    63.                 m_sliders[ingredient.Key].value = ingredient.Value.Progress;
    64.  
    65.             if (m_text.ContainsKey(ingredient.Key))
    66.                 m_text[ingredient.Key].text = ingredient.Value.ToString();
    67.         }
    68.     }
    69.  
    70.     Dictionary<ingredientTypes, CIngredient> m_ingredients = new Dictionary<ingredientTypes, CIngredient>();
    71.     Dictionary<ingredientTypes, Slider> m_sliders = new Dictionary<ingredientTypes, Slider>();
    72.     Dictionary<ingredientTypes, Text> m_text = new Dictionary<ingredientTypes, Text>();
    73. }
     
  5. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8
    Thanks for the code. Truth is, i'm not really sure how to use this XD
    The Class defines ingredients and the way you build it, they can be added , but what i find difficult to implement, is a way to make a single prefabs, generate different ingredients. if i istantiate, let say, 4 prefab of the same object, how can i say to each of them to produce different things? If i have to create different prefabs, for each ingredient, i fear to slow the game too much [and if i have to change things during tests it become a very time-consuming thing XD]
    If you dont mind, can you shom me how you will solve that with a gameobject who can pickup the different ingredients? probably with that code under my eyes i can undestand it better.
    Anyway thanks for your time, very appreciated ^^
     
  6. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    One way of doing this could be to create a ScriptableObject (SO). Here is some altered code creating an ingredient as a SO:
    Code (CSharp):
    1. [CreateAssetMenuAttribute(fileName = "Ingredient", menuName = "Ingredient")]
    2. public class CIngredient : ScriptableObject
    3. {
    4.     public enum ingredientTypes { flour, sugar, biscuits, cheese };
    5.     public float Progress { get { return m_currentTimer / m_maxTimer; } }
    6.     public int Units { get { return m_productUnits; } }
    7.     public ingredientTypes Type { get { return m_type; } }
    8.  
    9.     public bool Grow
    10.     {
    11.         get { return m_start; }
    12.         set
    13.         {
    14.             m_start = value;
    15.             m_currentTimer = 0;
    16.         }
    17.     }
    18.  
    19.     public void NextStep()
    20.     {
    21.         if (m_start)
    22.         {
    23.             m_currentTimer += Time.deltaTime;
    24.  
    25.             if (m_currentTimer > m_maxTimer)
    26.             {
    27.                 Grow = false;
    28.                 m_productUnits++;
    29.             }
    30.         }
    31.     }
    32.  
    33.     bool m_start;
    34.     float m_currentTimer;
    35.     int m_productUnits;
    36.  
    37. #pragma warning disable 649
    38.     [SerializeField] ingredientTypes m_type;
    39.     [SerializeField] float m_maxTimer = 3f;
    40. #pragma warning restore 649
    41. }
    If you compile this, then in the Editor menu, go Asset => Create => Ingredient. Give the new ingredient a name and select its type in the inspector.

    You will need to adjust the IngredientManager to accept this new type. Maybe something like this:
    Code (CSharp):
    1. using ingredientTypes = CIngredient.ingredientTypes;
    2.  
    3. public class IngredientManager : MonoBehaviour
    4. {
    5.     public bool Contains (ingredientTypes ingredient)
    6.     {
    7.         return m_ingredients.ContainsKey(ingredient);
    8.     }
    9.  
    10.     // Call Contains before calling this.
    11.     public CIngredient this [ingredientTypes ingredient]
    12.     {
    13.         get { return m_ingredients[ingredient]; }
    14.     }
    15.  
    16.     public void Add(ingredientTypes ingredient)
    17.     {   // Note: this will overwrite any previous instance of the same ingredient.
    18.         m_ingredients[ingredient] = new CIngredient();
    19.     }
    20.  
    21.     public void Grow(ingredientTypes grow)
    22.     {
    23.         if(m_ingredients.ContainsKey(grow))
    24.             m_ingredients[grow].Grow = true;
    25.     }
    26.  
    27.     void Update()
    28.     {
    29.         foreach (var ingredient in m_ingredients)
    30.         {
    31.             ingredient.Value.NextStep();
    32.         }
    33.     }
    34.  
    35.     Dictionary<ingredientTypes, CIngredient> m_ingredients = new Dictionary<ingredientTypes, CIngredient>();
    36. }
    You will, of course, want to extract the
    Progress
    and the
    Units
    from the ingredients to display in your UI (Sliders, Texts, etc.).

    Again, this code is untested but hopefully offers you some ideas?
     
    FeniceArcana2 likes this.
  7. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8
    Yes the code was inspiring, at least what i can grasp of it. Seems i'm still too noob to fully understand all of it. But i did as you sayd, creating new Ingredient into the assets. But they are scriptable object and i'm not familiar with how to extract theyr data into game object XD I have to create a new script, to do so, and attach to some gameobject probably. i will try it ^^
    Thanks for your tips, i'm learning something new *_*
     
  8. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8
    BTW if i can ask another advice...

    if i want to test this, i need some hints.

    i want to create a first script, let say a simple class with just one int:

    class Alpha : monobehavior
    {
    int something = 5;
    }

    if i have a second script and i want to pass the something value into another "int", how can i do it?

    i've tryed just to say, in the second script:

    class SecondClass : monobehavior
    {

    public void SomeMethod ()

    {
    int secondsomething = Alpha.something;

    }
    }

    obviously it doesn't work XD i was too naive
     
  9. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    To answer in the simplest terms, the calling code needs 2 things: (1) access to the target object and (2) permissions to read the value. To deal with each point in turn:

    (1) Access to the target object. There are a number of ways of doing this including (a) a Singleton object, (b) call GameObject.Find or (c) have a reference variable that is set in the Editor.

    (2) Permission to read. This means that there must be an accessor with an appropriate access modifier. For discussion, let's stick with
    public
    for the moment. However, try to avoid having public variables. Rather, prefer something like this because it adheres to information hiding and is considered generally safer to use and easier to manage :
    Code (CSharp):
    1. // This method can be called by anything that has access to this object.
    2. public int ReadPrivateValue { get { return m_thisValueIsPrivate; } }
    3.  
    4. // This value is hidden from everyone except this class.
    5. int m_thisValueIsPrivate;
     
  10. FeniceArcana2

    FeniceArcana2

    Joined:
    May 24, 2018
    Posts:
    8
    Thanks, and sorry if i replyed so late, i forget to check in for some days!
    i think i got it, i'll try.
    Thanks for your time ^^
     
    Doug_B likes this.