variable clutter

Hi. let me start by saying, im very new to all this. im new to coding, and im new to unity, so please consider that if you respond to my post.

im currently playing around with code for creating a battle simulation. the basis of the idea being, 2 armies meet, and based on the statistics of each army, one will defeat the other, and the information of the battle will be spit out at the end, in the form of a battle log.

The first thing that has hit me, is just how many variable are involved. There at least three types of troops, each troop has 6 attributes, and thats just on the player side, there will have to be enemy variables accounted for also. Just listing these variables is quickly becoming, a bit of an eye sore. For example:

int ArcherAtk = 4;
int ArcherDef = 2;
int ArcherHp = 10;
int ArcherRng = 30;
int ArcherSpd = 10;
int ArcherNmbr = 100;

Is there a way, to perhaps shorthand this information into something more palatable?

Int Archer: Atk = 4; Def = 2; Hp = 10; Rng = 30; Spd = 10; Num = 100;

or something along those lines please?

Yep, make Archer and each type of troop a class. All attributes go inside the class. However, if “ArcherNum” is the total number of archers, that wouldn’t be in the class, it would be in a Manager-type script. Check out how to create classes and instantiate them, they’re exactly what you need.

Here’s a rough example, just to illustrate. This sets up the class, then creates an array of 10 Archers, giving them some default values as well as a random one. (Untested but should be close.)

class Archer {
int atk;
int def;
int hp;
int rng;
int spd;
}
Archer[] archerList = new Archer[10];
for (int i=0; i<archerList.Length; i++) {
archerList[i] = new Archer();
archerList[i].atk = 2;
archerList[i].def = 4;
archerList[i].hp = Random.Range(5, 20);
//etc....
}
1 Like

sweet. thank you for your reply, its given me plenty of food for thought.

a question regards this part:

  • Archer[ ] archerList = new Archer[10];
  • for (int i=0; i<archerList.Length; i++) {
  • archerList = new Archer();

am i right in thinking this part of the code deals with numbers of troops? the i value attributing that number to the stats below?

If you want to develop a game I strongly recommend to learn the basics of programming first (preferably outside of Unity). A good resource is the free C# yellow book by Rob Miles. When you have a basic understanding of general programming do some Unity tutorials to learn its tools and workflow. When you have done that THEN you can tackle your project. There is little sense and chance of success to make your “dream” project without even knowing the bare basics. And you need those basics every day so you can’t always ask the forums. So do yourself a favor and learn those basics first. When you do it you can already write down which aspects relate to your game, how you would solve certain issues etc.
Good luck.

1 Like

hi. its good advice.

its more or less what i am doing tbf.

Im teaching myself C# via a program called sololearn atm. and i asked this particular question as part of a little exercise i set myself to better understand loops and conditionals and such, in such a way that relates to what i eventually hope to achieve.

ill check out that link you posted. thank you.

2 Likes

Good advice for sure. The more you absorb before diving in too far, the better progress you’ll make. That said, you will always come across challenges you can’t immediately solve, and those challenges just get more complex…and there’s no way to prep for everything you might run into. It’s fun but can be frustrating too. Errors are your friends, not your enemies. They are telling you how to change things!

Archer[] archerList = new Archer[10];
for (int i=0; i<archerList.Length; i++) {
archerList[i] = new Archer(); // note the i
  1. Create an array that will hold 10 Archers (we’ve defined an Archer class, so we can create instances of them)
  2. Start a loop that will run 10 times (once for each slot in the array…as of now, that array is ready with 10 slots, but the slots are empty)
  3. Instantiate (using “new”) an instance of Archer at slot “i”. This effectively fills up all 10 slots with Archers. Always count from 0, so in this case, i=0 through i=9.

Later you can change archer properties like this:
archerList[4].atk = 50;
This gives the 5th (! count from 0 !) archer a wicked attack ability.

In your class you can also write methods, like shoot(). Then you can call them:

archerList[8].shoot();

Side note: careful if you copy code in this forum that’s not in code format. having an “i” inside square brackets is a formatting tag (for italics) and will be erased!

2 Likes

I would suggest a serializable struct to organize these stats, and reference that in a MonoBehaviour, or - even better - a ScriptableObject that in turn is used in MonoBehaviours (basically a “UnitDefinition”). To save on code, in my example below, i made the fields top level members of the Scriptable object though, but you could do the same as in the ArcherBehaviour class.

using System;
using UnityEngine;

[Serializable]
public struct UnitStats //this could go in UnitStats.cs, but not mandatory
{
    public int Atk;
    public int Def;
    public int Hp;
    public int Rng;
    public int Spd;
    public int Num;
}

public class ArcherBehaviour : MonoBehaviour
{
   public UnitStats stats = new UnitStats() { Atk = 4, Def = 2, Hp = 10, Rng = 30, Spd = 10,  Num = 100 };
}

You can also edit the data from the inspector for that unit.

6995447--826376--upload_2021-4-1_2-22-54.png

Slightly more useful from a production standpoint:

ScriptableObject will require (enable!) you to edit it and wire it up in the inspector by dragging the UnitDefinition assets into the fields on the behaviours that use them; and you would probably initialize it with data from the inspector, too. You instantiate these from the Asset menu or by right-clicking into the Project tab. (not hierarchy tab). You can handle them like prefabs or any other assets. The CreateAssetMenu attribute enables this menu entry, and you specify the names there.

A major advantage is that you can treat game balance like an asset and you can edit these Scriptable objects at play time to rebalance without restarting, and they get saved immediately.

Adding a new and similar unit type (like, crossbowmen or longbow archers) would ideally require zero code, just a new UnitDefinition and a Game objects
with the right graphics.

using UnityEngine;

[CreateAssetMenu(menuName = "My Game/Unit Definition", fileName = "New Unit Stats Definition", order = 0)]
public class UnitDefinition : ScriptableObject //must go into a file named UnitDefinition.cs
{
    public int Atk;
    public int Def;
    public int Hp;
    public int Rng;
    public int Spd;
    public int Num;
}

And then it can look like this in your project and inspectors, the things with the blue wire box and amber braces are Assets (persistent instances) created from the Scriptable Object class UnitDefinition :

The UnitBehaviour contains only public UnitDefinition stats;, but in your case it would also deal with moving the unit, having it attack, etc. In that behaviour, you can access the variables through stats.Atk, for example. Please note that if you change them, they change for all objects, so your unit should probably have its own currentHp variable, for example.

In theory and practice, you could write a custom property drawer to make the stats editable visible from everywhere, but that’s an advanced scripting topic I would save for later. It’s safer to edit the assets with the balance values anyway.

2 Likes

this is some really good info. thank you!