Using string to refer to variable

Hi guys,

not sure if my question from the title is correctly formulated. I am working on a 2D Game like Fallout Shelter. I have one script for all my production buildings, no matter of what ressource it is producing. This has worked so far, but as i want to refer to a different script (ressourcemanager) where i add either wood or food, i ended up with 2 code snippets which are very similar, but for the different variable they change in my ressourcemanager.

public void CollectRessources()
{
    // FOOD PRODUCTION
    if (ressource == "Food")
    {
        if (ressourceManager.food != ressourceManager.foodLimit)
        {
            AddGold();
            if (ressourceProduced + ressourceManager.food > ressourceManager.foodLimit)
            {
                ressourceProduced += ressourceManager.food - ressourceManager.foodLimit;
                ressourceManager.food = ressourceManager.foodLimit;
                ressourceManager.UpdateFood(0);
                // Start Production again if Storage was full
                if (storageFull)
                    RestartProduction();
            }
            else
            {
                ressourceManager.UpdateFood(ressourceProduced);
                ressourceProduced = 0;
                collectIcon.SetActive(false);
                if (storageFull)
                    RestartProduction();
            }
        }
    }
    // WOOD PRODUCTION
    if (ressource == "Wood")
    {
        if (ressourceManager.wood != ressourceManager.woodLimit)
        {
            AddGold();
            if (ressourceProduced + ressourceManager.wood > ressourceManager.woodLimit)
            {
                ressourceProduced += ressourceManager.wood - ressourceManager.woodLimit;
                ressourceManager.wood = ressourceManager.woodLimit;
                ressourceManager.UpdateWood(0);
                if (storageFull)
                    RestartProduction();
            }
            else
            {
                ressourceManager.UpdateWood(ressourceProduced);
                ressourceProduced = 0;
                collectIcon.SetActive(false);
                if (storageFull)
                    RestartProduction();
            }
        }
    }

I am sure there is a better way to solve this, but i did not find anything helpful yet. It would be great if someone can point me in the correct direction. I thought something like this might work, but it doesnt:

public string ressource // this is either “food” or “wood”, depending on the building
ressourcemanager.[ressource] or something like this…

Since C# is object oriented, you might aswel make use of that.

You could create a template for your resources, unity has a nice way of creating and visualising data using ScriptableObjects

[CreateAssetMenu(fileName = "Resource", menuName = "Resource")]
public class ResourceConfig : ScriptableObject
{
    public string Name;
    public int Limit;
}

Create new resource template objects in your folder for each wood, gold etc…

Then assign them somewhere in inspector to your class

// Our actual resource class we will use
public class Resource
{
    public string Name;
    public int Limit;
    public int Amount;
}

// Base class for all your production buildings
public abstract class ProductionBuilding : MonoBehaviour
{
    [SerializeField]
    private ResourceConfig[] _resources;

    public Resource[] CurrentResources { get; private set; }

    public virtual void Start()
    {
        InitializeResources();
    }

    private void InitializeResources()
    {
        CurrentResources = new Resource[_resources.Length];
        for (int i=0; i < _resources.Length; i++)
        {
            CurrentResources *= new Resource()*

{
Name = resources*.Name,
Limit = _resources.Limit,*

Amount = 0,
};
}
}
}
public class Woodcutter : ProductionBuilding
{
// In inspector u can assign wood here as resource for example
public override void Start()
{
base.Start(); // Always call base if you wanna override start method
Print(); // Log all selected resources
}
// Custom logic for this production building
public void Print()
{
foreach (var resource in CurrentResources)
{
Debug.Log("Name: " + resource.Name + " | Amount: " + resource.Amount);
}
}
}
So for example the woodcutter class you would assign to your gameobject in inspector
and assign your resource templates.
this will be your implementation of the ProductionBuilding class, that class is abstract that
means it cannot be put in the inspector. (Intentional)
Each implementation will have CurrentResources which contains an instance of the selected resources.
*SCRIPTABLE OBJECTS in Unity - YouTube

You might try thinking about it more as general functions and a class for Resource. There’s a lot of things you could do, but as a basic example to get from where you are now, you could try something like this:

class Resource {
    string name;
    int amount;
    int limit;
}

And your ResourceManager can have both general types instead of the specific values (you might use a List or Dictionary if there were a lot of resource types):

class ResourceManager { // Don't know what you have here already
    Resource wood;
    Resource food;

    public Resource GetResource(string name) {
        if (name == "food") return food;
        if (name == "wood") return wood;
    }
    ...

Then, instead of your above two duplicate snippets, you’d call a function:

AddResource(resourceManage.GetResource("food"));
AddResource(resourceManage.GetResource("wood"));

void AddResource(Resource resource) {
   if (resource.amount != ressource.limit)
     {
         AddGold();
         if (ressourceProduced + ressource.amount > ressource.limit)
         { .... you fill in the rest
    }

Thanks a lot for the answer! It seems to me though, that i will have to read more about global classes in order to get everything going there. I was able to use the parts you provided, but now i can not find out how to set the variables i defined in the new Ressource class… Thanks anyway for your help here :slight_smile: