Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

onClick function does not detect Dictionary

Discussion in 'Scripting' started by MyMiniGemini, Jan 30, 2020.

  1. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    Hello Gurus

    I would like to ask you a question, if you dont mind.

    I dot a script with a function, in the Start Method I create a new dictionary and then add some keys and values to it.
    Also in the same script there is a function that changes value of a certain key, that is being passed to it by the onCLick button event set up in the inspector.

    Later in the game I got a button that passes a string of a key to that function and according to which key I get, the value is being change by a certain amount.

    1. If I access this function from within the other script, it works fine and changes the value with no problems.

    2. When I access this function from a button from the inspector, setting onClick to this button to send string, it sends the string across, but when Im trying to change a value for a received string Key it does not detect any Dictionary, so I need to reinitialize a Dictionary again for it to work.

    Maybe there is a solution that would let me operate the dictionary of the script through a Button from the inspector as I do not really want to create another Dictionary as it really messes and twists things up.

    Thank you in advance

    MMG
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,998
    Maybe need to see some parts of that script to check, like whats the difference between #1 and #2 methods?
     
  3. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    There is no difference except that one is being called from another script, so before calling this function the actual script, where the function is, is being initialized and a Dictionary as well. Another method is being called tom the UI button click and I assume that it does not go beyond and above that function and as a result Dictionary is missing. I would think UI button onClick would take variables and all the rest from the script, but as I can see it does not. Well at least it is what i can understand from digging into for quite a some time.
     
  4. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    I believe @mgear politely requested that you post your code. And please use code tags.
     
  5. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    Oh sorry, pretty new here, will do when back home from work.
     
  6. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    So in this script in function AddAmmo im passing a String from a button click:

    OnClick.JPG

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CharacterStatsChanger : MonoBehaviour
    6. {
    7.     CharacterLinkage linkToCharStats;
    8.     CollectablesLinkage linkToItems;
    9.     public int curretCharArmor;
    10.     public int currentCharHealth;
    11.     public Dictionary<string, int> weaponsList;
    12.     public int globalAmmoLeft;
    13.  
    14.     void Awake()
    15.     {
    16.  
    17.     }
    18.  
    19.     // Start is called before the first frame update
    20.     void Start()
    21.     {
    22.  
    23.         weaponsList = new Dictionary<string, int>();
    24.         InitalizingStats();
    25.         InitalizingWeapons();
    26.     }
    27.  
    28.     // Update is called once per frame
    29.     void Update()
    30.     {
    31.  
    32.     }
    33.  
    34.     public void Heal(int amount)
    35.     {
    36.         if (currentCharHealth == 100)
    37.         {
    38.             Debug.Log("HEALTH IS FULL");
    39.         }
    40.  
    41.         if (currentCharHealth < 100)
    42.         {
    43.             currentCharHealth = Mathf.Clamp(currentCharHealth + amount, 0, 100);
    44.             Debug.Log("HEALED " + currentCharHealth);
    45.         }
    46.     }
    47.  
    48.     public void AddAmmo(string weaponName)
    49.     {
    50.         Debug.Log(weaponName);
    51.         Debug.Log(weaponsList[weaponName]);
    52.         //weaponsList[weapon] += linkToItems.ReturnItemValue(weapon);
    53.         //Debug.Log(linkToItems.ReturnItemalue(weapon));
    54.     }
    55.  
    56.  
    57.     public void UseAmmo(string weapon)
    58.     {
    59.         weaponsList[weapon] -- ;
    60.         globalAmmoLeft = weaponsList[weapon];
    61.         Debug.Log(weaponsList[weapon]);
    62.     }
    63.  
    64.    public void InitalizingWeapons ()
    65.     {
    66.         weaponsList.Add("Pistol", 100);
    67.         weaponsList.Add("AK47", 200);
    68.     }
    69.  
    70.     void InitalizingStats()
    71.     {
    72.         currentCharHealth = linkToCharStats.characterLife;
    73.         curretCharArmor = linkToCharStats.characterArmor;
    74.     }
    75.  
    76. }
    And from this code im doing the same from the function ShotTheWeapon ( line 69), and passing a string into the Function UseAmmo, which if you check works absolutely the same

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class WeaponShoot : MonoBehaviour
    6. {
    7.     WeaponLinkage linkToWeaponStats;
    8.     public CharacterStatsChanger changingCharStats;
    9.  
    10.     [Header("Weapon Parts")]
    11.     public GameObject bullet;
    12.     public GameObject firingPoint;
    13.     public GameObject muzzle;
    14.     public GameObject shell;
    15.     public GameObject shellOutSlot;
    16.     public Light muzzleLighting;
    17.     float shelOutSpeed;
    18.  
    19.     float shotTimer;
    20.  
    21.     float shotSpeedDelay;
    22.     bool reloading;
    23.     int bulletsLeft;
    24.     //int reloadingTImer;
    25.     // Start is called before the first frame update
    26.     void Start()
    27.     {
    28.         muzzleLighting.enabled = false;
    29.         linkToWeaponStats = GetComponent<WeaponLinkage>();
    30.         shotTimer = 0;
    31.         reloading = false;
    32.         bulletsLeft = linkToWeaponStats.weaponAmmoCount;
    33.         shelOutSpeed = 20;
    34.  
    35.     }
    36.  
    37.     // Update is called once per frame
    38.     void Update()
    39.     {
    40.  
    41.         if(Input.GetKey(KeyCode.R))
    42.         {
    43.             StartCoroutine(ReloadTheWeapon());
    44.         }
    45.      
    46.         if (Input.GetMouseButton(0) && linkToWeaponStats.weaponShotSpeedDelay < shotTimer && !reloading)
    47.         {
    48.             bulletsLeft--;
    49.  
    50.             if (bulletsLeft == 0)
    51.             {
    52.                 StartCoroutine(ReloadTheWeapon());
    53.             }
    54.  
    55.             ShootTheWeapon();
    56.            // muzzleLighting.enabled = false;
    57.         }
    58.  
    59.         shotTimer += Time.deltaTime;
    60.      
    61.     }
    62.  
    63.     void ShootTheWeapon()
    64.     {
    65.         muzzleLighting.enabled = true;
    66.         GameObject muzzleInstance = (GameObject)Instantiate(muzzle, firingPoint.transform.position, Quaternion.identity);
    67.         StartCoroutine(MuzzleFlash());
    68.         GameObject bulletInstance = (GameObject)Instantiate(bullet, firingPoint.transform.position, Quaternion.identity);
    69.         changingCharStats.UseAmmo(linkToWeaponStats.weaponName);
    70.         Vector3 shootDirection = firingPoint.transform.forward;
    71.         WeaponBulletShot passToBullet = bulletInstance.GetComponent<WeaponBulletShot>();
    72.         passToBullet.GetDirection(shootDirection);
    73.         passToBullet.GetRange(linkToWeaponStats.weaponRange);
    74.         GameObject shellInstance = (GameObject)Instantiate(shell, shellOutSlot.transform.position, Quaternion.identity);
    75.         Rigidbody shellRB = shellInstance.GetComponent<Rigidbody>();
    76.         shellRB.AddForce(transform.forward * shelOutSpeed);
    77.         DestroyInstances(muzzleInstance, shellInstance);
    78.         shotTimer = 0;
    79.     }
    80.  
    81.     IEnumerator ReloadTheWeapon()
    82.     {
    83.         reloading = true;
    84.         yield return new WaitForSeconds(linkToWeaponStats.weaponReloadSpeed);
    85.         reloading = false;
    86.         bulletsLeft = linkToWeaponStats.weaponAmmoCount;
    87.     }
    88.  
    89.     IEnumerator MuzzleFlash()
    90.     {
    91.         yield return new WaitForSeconds(0.05f);
    92.         muzzleLighting.enabled = false;
    93.     }
    94.  
    95.     public void UpdateWeaponStats ()
    96.     {
    97.         bulletsLeft = linkToWeaponStats.weaponAmmoCount;
    98.         reloading = false;
    99.     }
    100.  
    101.     void DestroyInstances (GameObject vfxInstance01, GameObject vfxInstance02)
    102.     {
    103.         Destroy(vfxInstance01, 2);
    104.         Destroy(vfxInstance02, 10);
    105.     }
    106. }
    107.  
    So First option does no see the dictionary unless i do relaunch Start function before changing the Dictionary value.
     
    Last edited: Jan 30, 2020
  7. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    8,998
    so the error happens on this line? (whats the actual error message?)
    Code (CSharp):
    1. changingCharStats.UseAmmo(linkToWeaponStats.weaponName);
    before that line can you print out the value,
    Code (CSharp):
    1. Debug.Log(changingCharStats);
    2. Debug.Log(linkToWeaponStats);
    3. Debug.Log(linkToWeaponStats.weaponName);
     
  8. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    Not really, the error is on the line (51) in AddAmmo function after i click a button (image on the very top), the one you mentioned, works fine, that is why I'm confused.

    -
    Code (CSharp):
    1. Debug.Log(weaponsList[weaponName]);
    And the error is (
    Object reference not set to an instance of an Object C#)

    If I use start method in a function it finds a Dictionary and works fine.
     
  9. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,064
    Is the gameobject that contains the WeaponShoot component active or inactive?
    If the gameobject is inactive it won't call Start and then it won't initialize the weaponsList dictionary.

    Add a debug log with gameObject as context (second parameter of Debug.Log, when you click on the debug log it will highlight the gameObject in the hierarchy) in the Start method, does it get executed before you clicking the button?
     
  10. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    Well, this button gets instantiated in the inactive GameObject (inventory, inactive by default), when I pick up item. Though when i open the inventory it becomes active, and only then Im able to press the button.
    About the Start, it is a good question, I was thinking is UseAmmo function functions properly, then the Dictionary is being Initialized and means that Start is being launched, though, when I click the button, it appears that it is not or there is another reason.
    Will try to perform suggested thing when ill come back home from work, as always, wish I could stay and do this only thing :)
     
    Last edited: Jan 31, 2020
  11. MyMiniGemini

    MyMiniGemini

    Joined:
    Jan 25, 2014
    Posts:
    24
    Oh well ill rework my inventory with JSon database, i think it will be more practical in this case rather than scriptable objects. Thanks anyway, when I'll reach the stage when i will need to use an Item from the Inventory I will see how will it work in that case.