Floating point numbers are not exact!
1.05 can as well be 1.049999999 or 1.050000001 (or similar).
In this exact case e.g. 1.0499999523162841796875.
Instead of casting (int) which always simply cuts of the decimals simply use Mathf.RoundToInt which would result in 105 as well without the need for heavier data types (like double or decimal)
Hi everyone.
Im struggling to convert a float to an int and ive done reading up but cant seem to figure out what im doing wrong. I want health to be converted it the health display int so i cant dispaly it as a string.
here is my code
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement;
namespace Daniel { public class Living : MonoBehaviour, IDamagable { public float startingHealth; [SerializeField] protected float health; protected bool dead; [SerializeField] int healthDispaly;
public event System.Action OnDeath;
public virtual void Start()
{
health = startingHealth;
}
public void Update()
{
healthDispaly = (int)health;
}
public void TakeHit(float dmg, RaycastHit hit)
{
TakeDamage(dmg);
}
public void TakeDamage(float dmg)
{
health -= dmg;
if (health <= 0 && !dead)
{
Die();
}
}
public void Die()
{
dead = true;
if(OnDeath != null)
{
OnDeath();
}
GameObject.Destroy(gameObject);
if (gameObject.tag == ("Player"))
{
SceneManager.LoadScene("mapblocked");
}
}
}}
EDIT :: Solved it. I was using the wrong float value, not my actual health value.
C# float to int conversion problem (in Unity) - Stack Overflow
Possible to convert a Float into an Int? - Questions & Answers - Unity Discussions
Converting float to integer - UI - Unity Discussions
c# - How can I convert float to int? - Stack Overflow
You've just got a precedence problem. You've got:
(int) x + y
which is equivalent to
((int) x) + y
... which will then promote the result of the cast back to a float in order to perform floating point addition. Just make the cast apply to the whole result instead:
(int) (x + y)
Where x and y are the rather long expressions in your original code, of course. For the sake of readability, I'd extract the two values to separate local variables, so you'd have:
int sumX = (int) (Terrain.activeTerrain.transform.position.x + tilePositionInLocalSpace.x);
int sumY = (int) (Terrain.activeTerrain.transform.position.z + tilePositionInLocalSpace.y);
cube1.name = string.Format("Terrain_{0}_{1}", sumX, sumY);
Or better still:
var position = Terrain.activeTerrain.transform.position;
int sumX = (int) (position.x + tilePositionInLocalSpace.x);
int sumY = (int) (position.z + tilePositionInLocalSpace.y);
cube1.name = string.Format("Terrain_{0}_{1}", sumX, sumY);
you need to cast both as int since now you are adding an int with a float which of course results to float. Try:
cube1.name = string.Format("Terrain_{0}_{1}", (int)(Terrain.activeTerrain.transform.position.x + tilePositionInLocalSpace.x), (int)(Terrain.activeTerrain.transform.position.z + tilePositionInLocalSpace.y))
Firstly, there are integers and floating-point numbers. Integers are always whole numbers, such as 0, 1, -32, 42 and 1337. On the other hand, floating-point numbers can have a fractional part: 0, 1, -32.1, 42.7 and 123.456788 are all valid floating-point numbers.
When converting between integers (int) and floating-point (float) numbers, you can do this:
int someInt = 42;
float someFloat = someInt; // 42.0f
But you can't do this:
float someFloat = 42.7f;
int someInt = someFloat; // ?
The reason the first conversion is possible, is that converting the integer number (int) to a floating-point number (float) does not change the number. It is a safe conversion, and therefore can be done implicitly.
The reason the second conversion is not allowed, is that converting the floating-point number (which may have a fractional part) to an integer number (that never has a fractional part) must drop the fractional part of the number, i.e. it becomes a different number. This is not safe, and can therefore only be done explicitly.
To explicitly convert one type of number to another, you use a cast. That's the parentheses before the number with the type of the number that you want to convert it to.
float someFloat = 42.7f;
int someInt = (int)someFloat; // 42
Note that the fractional part of the floating-point number was dropped. It's as if it has been rounded towards zero. If you want to round the floating-point number to the nearest whole number, use the Math.Round method.
float someFloat = 42.7f;
int someInt = (int)Math.Round(someFloat); // 43
Try this :
int numInt = (int)Math.Ceiling(numFloat);
msdn documentation
You may want Math.Round() or Math.Floor() by the way.
Example :
float numFloat = 1.5f;
int testCeiling = (int)Math.Ceiling(numFloat);
int testFloor = (int)Math.Floor(numFloat);
int testRound = (int)Math.Round(numFloat);
Console.WriteLine("testCeiling = {0}", testCeiling.ToString());
Console.WriteLine("testFloor = {0}", testFloor.ToString());
Console.WriteLine("testRound= {0}", testRound.ToString());
output :
testCeiling = 2
testFloor = 1
testRound= 2
You are almost done, the error is trying to say that you are using a float instead of an int.
Array index can only be integers, in your line:
zomz[unonumero] = Instantiate(regzom, spawns[Mathf.Round(Random.Range(0f, 10f))]);
You are using Mathf.Round(Random.Range(0f, 10f)) to get the random and then round it and that is a wise choice, so you have a random float number like 2.4f rounded to 2.0f, the problem is that it still a float, not an integer.
Matfh has a cool Round method that gives you an integer, you can use this Mathf.RoundToInt(), like:
zomz[unonumero] = Instantiate(regzom, spawns[Mathf.RoundToInt(Random.Range(0f, 10f))]);
I hope its clear :)
Mathf.Found returns a float, proof. That float is then being used as an index for spawns[]. Only ints are allowed for indexing.
void Start()
{
foreach (GameObject x in zomz)
{
zomz[unonumero] = Instantiate(regzom, spawns[(int)Mathf.Round(Random.Range(0f, 10f))]);
unonumero++;
}
}
Edit: Marco Elizondo's answer is better. Use Mathf.RoundToInt instead.