1
\$\begingroup\$

The Problem:

I'm building one of those empire/kingdom building games and so I am trying to create an efficient way of making a "ResourceManager" class handle the games resources (wood, food, iron, stone). I currently repeat a function 4 times to do the same thing.

Attempt 1:

I created a "Resource" class (abstract) and derived the four resources from it. In each resource there are multiple methods which are similar:

Example Food.CS:

    new public static void AddResources(int amount) {

    Player.currentFoodSupply += amount;
    foodText.text = Player.currentFoodSupply.ToString();
}

Compare to Iron.CS:

new public static void AddResources(int amount)
{
    Player.currentIronSupply += amount;
    ironText.text = Player.currentIronSupply.ToString();
}

The AddResource() function is static because I have other scripts (like buildings, when they get upgraded) needing to communicate with each resource. The base building class currently has a method like this:

public void DeductResources()
{
    Food.DeductResources(FoodCost);
    Wood.DeductResources(WoodCost);
    Iron.DeductResources(IronCost);
    Stone.DeductResources(StoneCost);
}

This seems like it's so repetitive that there needs to be a more efficient way to do this.

Attempt 2:

A "ResourceManager" class that anything to do with the 4 resources can go through this one script. I can update that one script instead of numerous scripts that does something with the resources.

Where I am undecided is this one:

public static void DeductResources(Resource resource, int amount)
{
    if(resource.GetType() == typeof(Food))
    {
        Player.currentFoodSupply -= amount;
        resource.resourceText.text = Player.currentFoodSupply.ToString();
    }
    else if (resource.GetType() == typeof(Wood))
    {
        Player.currentWoodSupply -= amount;
        resource.resourceText.text = Player.currentWoodSupply.ToString();
    }
    else if (resource.GetType() == typeof(Iron))
    {
        Player.currentIronSupply -= amount;
        resource.resourceText.text = Player.currentIronSupply.ToString();
    }
    else if (resource.GetType() == typeof(Stone))
    {
        Player.currentStoneSupply -= amount;
        resource.resourceText.text = Player.currentStoneSupply.ToString();
    }
}

It looks like it works and I can't see a way around calling the above method 4 times as I need to know how much food or wood to add or deduct.

Does anyone have any suggestions please on how to improve this code/call the method once?

I'm always willing to learn! Thank you

\$\endgroup\$
0

1 Answer 1

4
\$\begingroup\$

Here's a slightly different version of my previous answer about this kind of system.

The big idea is to move away from using differently-named variables for each resource, because then we need to write different code to access each one. Instead, we can treat them uniformly as members of a collection, indexed/keyed by a resource type.

First we define our types (we could do this in data too via a Type Object, if you want to be able to add new resources dynamically without re-compiling, eg. for mods & expansions)

public enum ResourceType : int {
    Food,
    Wood,
    Iron,
    Stone,

    // Ensure this entry is last and it will automatically keep track
    // if how many resources we have. (If we don't explicitly assign 
    // values anywhere to confuse the auto-numbering)
    TOTAL_COUNT
}

Then we define a resource holder that can process transactions on each of these resource types as needed:

public class ResourcePool {
    uint[] _resources = new uint[(int)ResourceType.TOTAL_COUNT];

    public int GetQuantity(ResourceType type) {
        return _resources[(int)type];
    }

    public void Add(ResourceType type, uint quantity) {
        _resources[(int)type] += quantity;
    }

    public bool TryDeduct(ResourceType type, uint quantity) {
        if(GetQuantity(type) < quantity)
            return false;

        _resources[(int)type] -= quantity;
        return true;
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Well that's exactly what I'm looking for...more efficient code lol there is nothing different in my Food, Wood, Iron, Stone (and whatever else I add later on) scripts, so your solution is great. One script to add resources and another to handle all their functionality. Thank you so much. \$\endgroup\$
    – Anon
    Mar 21, 2018 at 8:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .