How to do better arhitecture SO with conditions?

I have a scriptable object that stores data about a building, that then gets used in a script. Appart from name, GO and usual info, it also stores how should building behave with other buildings; For now this mostly comes in a form of nearby buildings. For example if I would want to have a building that will recive 1 gold for every nearby building with id 1, i would create new array element of resources, and set type to gold, resourceValue to 1, condition˛ to typeOfNearbyBuilding and requiredBuildingId to 1.
Is there a way to make the system simpeler, since I think this is way to complicated and wont transision well into more complex machanics.

public class BuildingSO : ScriptableObject
{
    [Serializable]
    public struct Resources 
    {
        public ResourceType type;
        public int resourceValue;
        public ResourcesConditions[] resourcesConditionsArray;
    }

    [Serializable]
    public struct ResourcesConditions 
    {
        public Condition condition;
        public int buildingRequiredId;
    }

    public enum ResourceType 
    {
        gold,
        food,
    }

    public enum Condition 
    {
        typeOfBuildingNearby
    }

    public string buildingName;
    public int buildingId;

    public Transform buildingTransform;

    [Header("Building Yields")]
    public Resources[] resources;
}

You could forget about trying to come up with a singular data structure that can represents the configurations of all different types of behaviours in the game, and instead create a simple abstract base class that can be implemented to define a new building behaviour:

public abstract class BuildingBehaviour : ScriptableObject
{
	public abstract void Perform(Building building);
}

Then you could add completely different types of serialized fields for every behaviour, and write whatever code you can imagine making use of them:

[CreateAssetMenu]
public sealed class RewardsForNeighbours : BuildingBehaviour
{
	[SerializeField] Condition<Building> condition;
	[SerializeField] Reward reward;

	public override void Perform(Building building)
	{
		foreach(var neighbour in building.Neigbours)
		{
			if(condition.Evaluate(neighbour))
			{
				reward.Give(building.Owner);
			}
		}
	}
}

The power of polymorphism.

3 Likes