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\$
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\$
  • \$\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 '18 at 8:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.