Question regarding setting up a stat system

I’ve been learning C# programming for about 4 weeks (Literally just started programming 4 weeks ago, never did it before), watched tutorials after tutorials, messed with code and read descriptions after descriptions. So here I am trying to setup a stat system for my game… Trying to keep this short:

I was trying to make it so I didn’t need a separate script for every character / enemy in my game but I gave up and just made separate scripts. (If any of you know how to achieve what I was trying to achieve I’d love to be pointed in the right direction).

So now I have a script for my character and enemy. Now it seems that the stats are calculating okay, but the debug.log is showing that my character is being hit TWICE and no matter how much I stare at this code, I can’t figure out why that’s happening.

On top of those two questions… Could anyone look at my code briefly and tell me if it’s bad? Suggestions? Is there an easier way to do this? Another thing that I think is a problem is that at the start of the void, it calculates some of my statistics, I think this might cause unintentional stat gain but I have no idea how to set this up otherwise. It’s all kinda messy right now because I am only concerned with it working before I start fixing stats properly though if something seems erroneous it would be REALLY appreciated if someone pointed out.

Kai’s stats in editor: http://puu.sh/8HLvr/5272c74624.png
Enemy’s stats in editor: http://puu.sh/8HLwn/56f80dcd92.png

using UnityEngine;
using System.Collections;

public class battleStart : MonoBehaviour {
	public kaiStats Kai;
	public enemycubeStats statsofCube;
	public bool battleBegin = false;

	void Start ()
	{
		// Enemy's Stats
		statsofCube.physicalAttack = statsofCube.strength * 0.5f + statsofCube.weaponDamage;
		statsofCube.magicAttack = .5f * statsofCube.intelligence;											
		statsofCube.hitChance = statsofCube.hitChance;
		statsofCube.dodge = statsofCube.agility * (Random.Range (0.1f, 0.3f));
		
		// Kai's Stats
		Kai.physicalAttack = Kai.strength * Kai.weaponDamage;
		Kai.magicAttack = .5f * Kai.intelligence;	
		Kai.hitChance = Kai.hitChance * (Random.Range (0.1f, 0.5f));
		Kai.dodge = Kai.agility * (Random.Range (0.1f, 0.3f));
		

	}

	void Update()
	{		
		if (Input.GetKeyDown ("g")) 
		{
				battleBegin = true;
		while (battleBegin) {	

				Kai.currentHealth -= Kai.defense - statsofCube.physicalAttack;
				battleBegin = false;
			}
			Debug.Log (Kai.currentHealth);
				}
               }
}
 using UnityEngine;
using System.Collections;
		
public class kaiStats : MonoBehaviour {

	public float
	level,
	maxHealth, 
	currentHealth, 
	strength, 
	intelligence, 
	agility, 
	defense, 
	magicDefense, 
	hitChance, 
	dodge, 
	magicAttack, 
	physicalAttack, 
	weaponDamage;
}
 using UnityEngine;
using System.Collections;
		
public class enemycubeStats : MonoBehaviour {
	public float
	level,
	maxHealth, 
	currentHealth, 
	strength, 
	intelligence, 
	agility, 
	defense, 
	magicDefense, 
	hitChance, 
	dodge, 
	magicAttack, 
	physicalAttack , 
	weaponDamage;
}

Thanks so much to anyone who can help me make this not suck. I really think if I can just be shown where I’m messing up and what code isn’t going to work, it will help me a lot.

Are you seeing the same debug message printed twice? Or is it one debug message showing that the character’s health got reduced two times?

If it’s the latter, then I think it’s because your Update method looks funny. The while loop is not needed at all since it will only run once anyways:

            while (battleBegin)
            {	
                Kai.currentHealth -= Kai.defense - statsofCube.physicalAttack;
                battleBegin = false;
             }

You can omit it altogether:

                Kai.currentHealth -= Kai.defense - statsofCube.physicalAttack;

And the above expression seems to be incorrect. I think you want to change it to:

                Kai.currentHealth += Kai.defense - statsofCube.physicalAttack;

Which won’t take care of the case when the defense is greater than the physical attack strength, which is something your might have when you add randomization and dice rolls and what have you. So you should change that to:

                var damage = statsofCube.physicalAttack - Kai.defense;
                if (damage < 0)
                    damage = 0;
                Kai.currentHealth -= damage;

I think that’s what’s causing the damage miscalculations that you’re seeing.

As to the rest of your code: It could definitely use some dusting up, but fix the damage issue first and go from there :slight_smile:

Alright!

void Update()
	{		
		if (Input.GetKeyDown ("g")) 
		{
			var damage = statsofCube.physicalAttack - Kai.defense;
			if (damage < 0)
			{
				damage = 0;
				Kai.currentHealth -= damage;
			}else
			{
				Kai.currentHealth += Kai.defense - statsofCube.physicalAttack;				
			}
			Debug.Log (Kai.currentHealth);

		}

I got it working with the suggestions you’ve made, though I had to put " Kai.currentHealth += Kai.defense - statsofCube.physicalAttack;" in an ‘else’.

I’m eager to hear some feedback regarding the dusting up of the way the stats are calculating. Also, is there a way to make it so I don’t need separate scripts for every player character / battle-able NPC? I’m just worried that all these scripts may bloat my game. What I mean is… I want to be able to use the same “strength, defense etc” floats for each character but still be able to apply different stats for each character.

I was doing that first and, while I could change the initial stats in the unity editor, I couldn’t actually call the component by object because the script was being attached to every character.

Not so fast.

The code snippet you posted might work, but consider this:

			if (damage < 0)
			{
				damage = 0;
				Kai.currentHealth -= damage;
			}

If that block is executed then damage will always be set to zero, meaning that you’ll always be subtracting zero from Kai.currentHealth, meaning that the whole block is effectively doing nothing. So you can reduce your code to the following:

void Update()
	{		
		if (Input.GetKeyDown ("g")) 
		{
			var damage = statsofCube.physicalAttack - Kai.defense;
			if (damage >= 0)
			{
				Kai.currentHealth += Kai.defense - statsofCube.physicalAttack;				
			}
			Debug.Log (Kai.currentHealth);

		}
	}

But Kai.defense - statsofCube.physicalAttack == -damage, the variable that you’ve already computed. So the above can be further reduced to:

void Update()
	{		
		if (Input.GetKeyDown ("g")) 
		{
			var damage = statsofCube.physicalAttack - Kai.defense;
			if (damage >= 0)
			{
				Kai.currentHealth -= damage;
			}
			Debug.Log (Kai.currentHealth);
		}
	}

As to other improvements that can be done to your code: I think that at this stage you would be better off slowing down and focusing on the basics of programming and C#. The calculations in your Update methods are quite elementary and the logic should be self-evident and trivial to anyone with basic knowledge of the fundamentals.

Thank you very much for your help. When you said that my code could use some improvement, I had assumed it was a drastic change from how it was laid out. But simply knowing that the changes are simple ‘cleanup’ I should be able to look at them in a different way and figure that out on my own.

I also felt that that code was doing nothing so it’s great to see that I am thinking the same way you are in that regard! You’ve been a very big help. I’m curious what you would recommend for someone learning to program by self-teaching with nobody to help me when it comes to trying to understand how certain things work or to figure out how to make something work when you simply have no idea how to use specific code.

I have overcome the very basics and with enough messing with things, I can make something work to an extent like this stat system was coded without help just sorta messed with things until it was doing something, and the calculations regarding the enemy dealing damage to Kai was also figuring it out on my own but I hit that wall where not even 7 hours of messing with it was helping.

I’m just trying to figure out what direction I should take and what resources i should use (besides the actual definitions of terms because that doesn’t actually help me know how to apply them).

You’re most welcome. But I think that your code will need major changes. My thoughts were that one should get things right on the method level before looking into the wider scope of class-level organization and design.

For example, there’s no need to have two classes (or scripts) for the stats. One would do:

public class Stats : MonoBehaviour
{
	public float level;
	public float maxHealth;
	public float currentHealth;

        // etc.
}

Note that it’s considered good form to name classes using Pascal casing (e.g. CharacterStats) instead of camel casing (e.g. characterStats). Note that it’s also good form to declare all fields separately instead of using a single statement like you were doing. And when I say “good form”, I mean agreed upon conventions often referred to as “coding styles.”

Now if you were to add the above script (or class) to both your Kai game object and EnemyCube game object, then you should be able to rewrite your battleStart class as follows:

public class battleStart : MonoBehaviour {
	public Stats Kai;
	public Stats statsofCube;
	public bool battleBegin = false;

        // rest of your code
}

Then your code should continue to work as expected without needing two sets of identical stat classes. I have no idea why that didn’t work for you, but it should.

But that’s still far from ideal. The whole point of Object-Oriented Programming (OOP) is to model real world objects (or abstractions thereof) in code. Your code indicates that you have two types of objects in your game: A player named Kai, and an EnemyCube. I’m over simplifying here, but these two objects should have their own two classes in code. And these classes should contain all the data that describe those objects and all the behavior (or methods) that represent what these objects can do or can be done to them.

You don’t have that in your code. What you have is a battleStart class that isn’t really needed here. If Kai is supposed to attack an enemy based on user input, then that code should belong in the Kai class. If the enemy is supposed to attack Kai based on some inputs or conditions, then the code that initiates that should exist in the Enemy class, and it should call a method on the Kai class that tells it “Hey, I just took a swing at you.” The Kai class should then calculate the damage and respond to it.

I don’t think you’ll get far without knowing the basics of the language and of programming before tackling the Unity-specific stuff. Some quality time with Visual Studio Express and a C# book is probably all you need. I’ve seen the C# Yellow Book (link) recommended frequently on these forums. You might want to work through it.

You can’t rush past the basics. You’ll just end up spending more time and effort learning them the hard way. Geekdom is a journey. Slow down and enjoy the ride :slight_smile:

/me gets off soapbox.