Same Code, Different Variables (Optimization)

I have an optimization question :

I have lines of code, repeating the same function over, and over, and over again, but each time it has a different variable. The problem for example I have some attributes I need, and I need to make sure that if it’s value is at 0, it won’t go negative. So I write my code like this :

void Update () {

if(energy <= 0){
energy = 0;
}
}

This code works, so when my energy becomes 0, it doesn’t go into the negative. But then I’m not just counting how much energy the player has, I’m counting health, ammo, power, mana, etc… So then I have to write the code like this :

void Update () {

if(energy <= 0){
energy = 0;
}

if(health <= 0){
health = 0;
}

if(power <= 0){
power = 0;
}

if(mana <= 0){
mana = 0;
}
}

Suddenly, I have more lines of code then I need and it checks for each of them every frame, making the script do more work. What I could make it do is check for it only under certain circumstances, not every frame, but even then, the code is longer and probably gives performance a hit. Is there another way of writing something like this? Here’s my code for my specific situation :

void Update () {
	
	if(health <= 0){
		health = 0;
	} 
	
	if(energy <= 0){
		energy = 0;
	} 
	
	if(speed <= 0){
		speed = 0;
	} 
	
	if(mana <= 0){
		mana = 0;
	} 
	
	if(power <= 0){
		power = 0;
	} 
			
	if(agility == maxAgility){
	canAddAgility = false;
	}
	else{
	canAddAgility = true;
	}	
	
	if(toughness == maxToughness){
	canAddToughness = false;
	}
	else{
	canAddToughness = true;
	}
	
	if(stamina == maxStamina){
	canAddStamina = false;
	}
	else{
	canAddStamina = true;
	}
	
	if(supernaturalFocus == maxSupernaturalFocus){
	canAddSupernaturalFocus = false;
	}
	else{
	canAddSupernaturalFocus = true;
	}
	
	if(strength == maxStrength){
	canAddStrength = false;
	}
	else{
	canAddStrength = true;
	}
	
	if(agility == minAgility){
	canSubtractAgility = false;
	}
	else{
	canSubtractAgility = true;
	}	
	
	if(toughness == minToughness){
	canSubtractToughness = false;
	}
	else{
	canSubtractToughness = true;
	}
	
	if(stamina == minStamina){
	canSubtractStamina = false;
	}
	else{
	canSubtractStamina = true;
	}
	
	if(supernaturalFocus == minSupernaturalFocus){
	canSubtractSupernaturalFocus = false;
	}
	else{
	canSubtractSupernaturalFocus = true;
	}
	
	if(strength == minStrength){
	canSubtractStrength = false;
	}
	else{
	canSubtractStrength = true;
	}
}

And for the GUI (same script) :

if(GUI.Button(new Rect(350, 60, 30, 25), "+") && canAddAgility && pointsLeft > 0){
	agility ++;
	pointsLeft --;
	StatusModifier();
}
 
if(GUI.Button(new Rect(350, 90, 30, 25), "+") && canAddToughness && pointsLeft > 0){
	toughness ++;
	pointsLeft --;
	StatusModifier();
}

if(GUI.Button(new Rect(350, 120, 30, 25), "+") && canAddStamina && pointsLeft > 0){
	stamina ++;
	pointsLeft --;
	StatusModifier();
}

if(GUI.Button(new Rect(350, 150, 30, 25), "+") && canAddSupernaturalFocus && pointsLeft > 0){
	supernaturalFocus ++;
	pointsLeft --;
	StatusModifier();
}

if(GUI.Button(new Rect(350, 180, 30, 25), "+") && canAddStrength && pointsLeft > 0){
	strength ++;
	pointsLeft --;
	StatusModifier();
}

if(GUI.Button(new Rect(380, 60, 30, 25), "-") && canSubtractAgility){
	agility --;
	pointsLeft ++;
	StatusModifier();
}

if(GUI.Button(new Rect(380, 90, 30, 25), "-") && canSubtractToughness){
	toughness --;
	pointsLeft ++;
	StatusModifier();
}

if(GUI.Button(new Rect(380, 120, 30, 25), "-") && canSubtractStamina){
	stamina --;
	pointsLeft ++;
	StatusModifier();
}

if(GUI.Button(new Rect(380, 150, 30, 25), "-") && canSubtractSupernaturalFocus){
	supernaturalFocus --;
	pointsLeft ++;
	StatusModifier();
}

if(GUI.Button(new Rect(380, 180, 30, 25), "-") && canSubtractStrength){
	strength --;
	pointsLeft ++;
	StatusModifier();
}

As you can see, the code is long, but it’s just doing basically the same thing over and over again, making the script long and giving it a performance hit. There must be another way to write this. Thanks in Advance.

The best and easiest way is to use properties, that's the real advantage of properties:

private float m_Health;

public float Health
{
    get {return m_Health;}
    set
    {
        m_Health = Mathf.Max(0,value);
    }
}

That way it get only checked when you change the value. It's also a good place to check for the player death or to play a hitsound or something like that.

Another advantage is if you have weird behaviour of your health var, you can put a Debug.Log in the setter to see when, how often and to what value it gets set.

edit

There are some disadvantages of course. The biggest one is that you can't show this variable in the inspector since it's not a variable. You could turn the private m_Health into a public var but make sure you don't set this variable from one of your scripts since it would bypass the check ...