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. Dismiss Notice

Question Can't understand why variables have such values

Discussion in 'Scripting' started by Kujji, Mar 24, 2023.

  1. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    I change the damage that is used in the bullet, I don't understand why I get such values in console.

    When damage is increased project crushes with this error:

    FormatException: Input string was not in a correct format. System.Number.ThrowOverflowOrFormatException (System.Boolean overflow, System.String overflowResourceKey) (at :0) System.Number.ParseSingle (System.ReadOnlySpan`1[T] value, System.Globalization.NumberStyles styles, System.Globalization.NumberFormatInfo info) (at :0)


    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class Bullet : MonoBehaviour
    4. {
    5. public float _damage;//_damage = 1
    6.  
    7. private float _currentDamage;
    8.  
    9. private void Start()
    10. {
    11.     _currentDamage = _damage;
    12. }
    13.  
    14. private void OnTriggerEnter(Collider other)
    15. {
    16.     if (other.gameObject.TryGetComponent(out Enemy enemy))
    17.     {
    18.         enemy.GetDamage(_currentDamage);// works right and attacks by value of _damage
    19.         Destroy(gameObject);
    20.     }
    21. }
    22.  
    23. public void IncreaseDamage(float damageMultiplier)
    24. {
    25.     float damageLong = _currentDamage * damageMultiplier;
    26.  
    27.     Debug.Log(_currentDamage + " " + damageMultiplier);//shows: 0 1.2
    28.  
    29.     string str = damageLong.ToString("#.##");
    30.  
    31.     Debug.Log(str);//shows: "nothing"
    32.  
    33.     _currentDamage = float.Parse(str);
    34. }
    35. }
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,883
    What is calling IncreaseDamage, and how is it being called? Perhaps you have an infinite loop causing the float to overflow?
     
    Kujji likes this.
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    May i ask why we are calculating a number, just to convert it to a string, to format it, and then parse it back to a number? I assume you want to get rid of all but 2 decimal places. But why? You arent actually multiplying with the damageMultiplier then anymore, but a value thats on average slightly smaller. Shouldnt the actual damage value represent the correct result of your calculation? If you then display that damage value somewhere, then you would want to format it to a more humanly readable format. Why do you care about truncating a value thats only used internally for calculations, to make it less accurate?

    The actual content of the function, other than the number truncation, can be summarized as:
    Code (CSharp):
    1. _currentDamage *= damageMultiplier;
    If you, for some reason, want to truncate the number right there, you might want to stick to math, not strings, since strings are kinda slow in comparison. https://social.msdn.microsoft.com/F...float-to-2-decimal-places?forum=csharpgeneral

    To actually debug your code i would suggest printing more values first, then testing what might go wrong. You wrote that _currentDamage is 0, and damageMultiplier is 1.2, so is damageLong 0 as we would expect? If so, does your ToString formatting line also crash if you execute it individually, somewhere else, on a hardcoded float with value 0f? I doubt we would see a formatting issue or an overflow error with a value of 0f (tho i didnt check for cornercases), but since you never actually printed the value of damageLong im just guessing around here.
     
    Kujji and Kurt-Dekker like this.
  4. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    It's called from other script, when button is pressed:

    Code (CSharp):
    1.     public void Power()
    2.     {
    3.         if (_slime.points > _powerPrice)
    4.         {
    5.             _bullet.IncreaseDamage(1.2f);
    6.         }
    7.     }
     
  5. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Yes i did this strange lines just to leave two decimal place. I checked, yes damageLong is equal to 0.
     
  6. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590

     
    Kujji likes this.
  7. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    I initialize _damage value in inspector, but as i understand main problem will happen because this script attached to bullet which appears and get destroyed with its script, so value _currentDamage won't be recorded anywhere, my idea was to increase damage other time but for every bullet its going to be different value as i understand, so i should change construction of increasing damage
     
  8. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    I believe this is a language barrier problem, but do you want damage to increase for all bullet? Or are you explaining that you dont want that? Unrelated to that, my main question was why you truncate the number to 2 decimal places, instead of simply leaving it with whatever precise value it would have after the calculation.
     
  9. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    Yes i want increase damage for all bullet, i truncate the number to 2 decimal place because i show this number in UI when bullet damages enemy.
     
  10. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,136
    A FormatException means that the string being generated is incorrectly formatted. One potential reason may be your culture info (ie commas instead of periods). Try seeing if this fixes the problem for you:
    Code (csharp):
    1. using System.Globalization;
    Code (csharp):
    1. public void IncreaseDamage(float damageMultiplier)
    2. {
    3.     float damageLong = _currentDamage * damageMultiplier;
    4.  
    5.     Debug.Log(_currentDamage + " " + damageMultiplier); //shows: 0 1.2
    6.  
    7.     string str = damageLong.ToString("#.##", CultureInfo.InvariantCulture);
    8.  
    9.     Debug.Log(str); //should now show a value
    10.  
    11.     _currentDamage = float.Parse(str, CultureInfo.InvariantCulture);
    12. }
    Alternatively you can truncate the digits with some simple math (though this can show floating point inaccuracies):
    Code (csharp):
    1. public void IncreaseDamage(float damageMultiplier)
    2. {
    3.     float damageLong = _currentDamage * damageMultiplier;
    4.  
    5.     Debug.Log(_currentDamage + " " + damageMultiplier); //shows: 0 1.2
    6.  
    7.     float truncatedDamage = Mathf.Round(damageLong * 100f) / 100f;
    8.     // The above line rounds the damage to two decimal places.
    9.  
    10.     Debug.Log(truncatedDamage); //should now show a value
    11.  
    12.     _currentDamage = truncatedDamage;
    13. }
     
    Last edited: Mar 26, 2023
    Kujji, Bunny83 and Yoreki like this.
  11. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    I mentioned this before, but you should not adjust the actual float value just because you eventually want to display it. You need to differentiate between the internal value, which you want to be precise and fast, and its external representation, which you may adjust however you want. One has nothing to do with the other, and the visual representation should not in any way affect the internal value. Grab the accurate value when you want to display it simply display the formatted string, instead of adjusting the actual underlying value.
     
    Kujji likes this.
  12. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    As everyone said before: You shouldn't truncate using strings. This is both prone to error, as well as bad for performance. If you absolutely have to truncate (e.g. to ensure consistency) there are functions such as Math.Truncate & Math.Round.
    That said; I'm guessing you're outputting
    .ToString("#.##")
    with a '.', whereas the
    float.Parse(str)
    is expecting a ','.
    Using CultureInfo.InvariantCulture, like @Ryiah suggested, should resolve this.
     
    Kujji likes this.
  13. Kujji

    Kujji

    Joined:
    Oct 20, 2021
    Posts:
    109
    I've done it like this:
    Code (CSharp):
    1. _slimeShooting.damage = (float)(Math.Round((double)longDamage, 2));