Int -= 1 * Time.deltaTime;

Hello i have a simpel shooting script and all it does for now is when ever i hold down my mousebutton it will widraw from my “ammo” thats an int (also does some animations). But it takes it away to fast. My ammo goes down from 30 to 0 in 0.001 secounds. Please help me!

Script (javaScript):

#pragma strict

var ammo : int;

private var canShot : boolean = true;

function Start ()
{
	GetComponent.<Animation>().Play("Mp5_Idle");
	ammo = 30;
}

function Update ()
{
	if(Input.GetMouseButton(0))
	{
		SprayMP5 ();
	}
	else
	{
		StopMp5();
	}
}

function SprayMP5 ()
{
	GetComponent.<Animation>().Play("Mp5_Shot");
	ammo -= 0.5 * Time.deltaTime;
	GetComponent.<Animation>().Stop("Mp5_Idle");
}

function StopMp5()
{
	GetComponent.<Animation>().Stop("Mp5_Shot");
	GetComponent.<Animation>().Play("Mp5_Idle");
}

function OnGUI ()
{
	GUI.Label(new Rect(30, 80, 150,50), ammo.ToString());
}

Yes, integers are whole numbers and cannot contain decimals.

So this line is deceptive (and honestly should not compile, but that’s what you get for using var instead of strong-typing):

ammo -= 0.5 * Time.deltaTime;

Here’s what that’s actually doing (every frame, so potentially 60 times per second). Let’s assume ammo is still at it’s maximum 30, and Time.deltaTime is perfect 60FPS or 0.016667. First frame:

Evaluate right side of equation to (0.5*0.016667) or 0.0833333

Subtract, but since the right side is floating point, do decimal subtraction so (30-0.0833333) or 29.9166667

Now apply the value, but since ammo is an int, we truncate the decimal portion, so it get’s set to 29.

So, basically each frame, you are subtracting by one, which in 60FPS means it gets cleaned out in half a second.

What you need to do is have a fire cooldown timer. Store a float for firing cooldown as a class variable. When the trigger is pressed, you fire only if the cooldown timer is less than or equal to zero. When you do successfully fire, set the cooldown timer to an appropriate value (e.g. 0.1 would be 10 bullets per second). Then each update you’ll reduce the cooldown timer by Time.deltaTime. That way it waits a few frames between the firing of each bullet.

You can also use coroutines for this sort of thing, but I’m more of an old-school manage-it-myself type.

Time.deltaTime adds up to a total of 1 every second.

So subtracting Time.deltaTime will subtract 1 from your ammo each second. 30 seconds to drain ammo.

Subtracting Time.deltaTime/2 will subtract 1 ammo every 2 each seconds (60 seconds to drain) etc.

But Time.deltaTime is a tiny fraction each frame, and you can’t subtract a tiny fraction from an integer.

You need to track ammo as a float instead. (Then you can always convert to int using Mathf.Floor or Mathf.Round when you set the visible label.)

(A separate issue is the question of whether you really want to play the Shot animation every frame. Probably not!)

#pragma strict

var ammo : int;
var cooldown : float;
    
function Start ()
{
    GetComponent.<Animation>().Play("Mp5_Idle");
    ammo = 30;
}
    
function Update ()
{
    if(Input.GetMouseButton(0)&&0<=ammo&&cooldown<=Time.time)
    {
        cooldown=Time.time+1f;
        SprayMP5 ();
    }
    else
    {
        StopMp5();
    }

    if(Input.GetKeyDown(KeyCode.R))
    {
        GetComponent.<Animation>().Stop("Mp5_Idle");
        GetComponent.<Animation>().Play("Mp5_Reload");
        StopReload();
    }
}
    
function SprayMP5 ()
{
    GetComponent.<Animation>().Play("Mp5_Shot");
    ammo -= 1;
    GetComponent.<Animation>().Stop("Mp5_Idle");
}
    
function StopMp5()
{
    GetComponent.<Animation>().Stop("Mp5_Shot");
    GetComponent.<Animation>().Play("Mp5_Idle");
}
    
function OnGUI ()
{
    GUI.Label(new Rect(30, 80, 150,50), ammo.ToString());
}

function StopReload ()
{
    yield WaitForSeconds(1.2);
    GetComponent.<Animation>().Stop("Mp5_Reload");
    ammo = 30;
}