What would be the vest way to structure a multi layer economy that allows both item to item as well as coin trade, the system starts at individual merchants which are tied to the town they're in, which is then tied to the lordship that town is in, which is them tied to the kingdom that lord serves. As of now I have each tier as a scriptable object that contains lists of scriptable objects and where as this makes there be less overall scripts it makes accessing specific data a little difficult, is there a better way I should be doing this? I wouldn't say I'm a beginner but all my knowledge is mostly self taught from Google so it's a bit limited
#Dynamic feudal economy
1 messages · Page 1 of 1 (latest)
If you want to make accessing a specific data easier, add references to that data as a field visible in the inspector, so you can set it up here either by dragging it from the project assets or simply selecting it from the list of objects of such a type. If you feel extra ambitious, you may even consider creating your own custom field drawers.
When it comes to logic, at the start of the game, you can precompute some data and cache it in a form of dictionaries to make it easier to access relevant data. For example, if you have a town that contains a list of merchants, you can create a dictionary that stores the info about which town contains a particular merchant.
Btw, keep in mind that ScriptableObjects are designed mostly to be fixed assets. They can be used as dynamically created and modified assets, but they would miss their purpose.
i see, ive seen structs used for similar things, would that be better than scriptable objects?
using NUnit.Framework.Internal.Commands;
using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
public class TownManager : MonoBehaviour
{
private TownSOHolder tso;
public Camera mainCamera;
private string targetTag = "Town";
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame) // Detect left mouse click
{
Ray ray = mainCamera.ScreenPointToRay(Mouse.current.position.ReadValue());
if (Physics.Raycast(ray, out RaycastHit hit))
{
if (hit.collider.CompareTag(targetTag)) // Check if the object has the specified tag
{
Debug.Log($"Hit object with tag: {targetTag}");
tso = hit.collider.gameObject.GetComponent<TownSOHolder>();
int totalStock = 0;
for (int i = 0; i < tso.TownSO.items.Count; i++)
{
string name = new string(tso.TownSO.items[i].Name);
int stock = new int();
stock = (tso.TownSO.itemStocks[i]);
Debug.Log("the stock of " + name + " is " + stock);
totalStock += stock;
}
tso.TownSO.totalGoods = totalStock;
Debug.Log($"Total stock: {tso.TownSO.totalGoods}");
//Debug.Log($"The town of {tso.TownSO.name} is stocked with");
// Add your logic here (e.g., interact with the object)
}
}
}
}
}
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "TownSO", menuName = "Scriptable Objects/TownSO")]
public class TownSO : ScriptableObject
{
public string Name;
public int totalGoods;
public List<ItemSO> items;
public List<int> itemStocks;
public List<MerchantSO> merchants;
}
this is the general idea of my framework
It's in the early stages since I didn't want to fully commit when I was doubting if I was being as efficient as possible
I usually use ScriptableObjects as configuration files or template files.
If you want to optimize the project perfectly, then structs may be handy, but be aware that they behave differently than classes (e.g., passing them as an argument creates a copy of them, unless you pass a pointer to them).
From my experience, when working on something new, it's difficult to predict what may work better in the future. Sometimes I lost more time thinking about solutions than actually coding. I think it's ok to make mistakes, as long as you haven't lost much time and you learned something new from it.
Alright that's a very good point
As for this, I've used structs before but not often for a similar project but don't remember much about them, I assume I can call on them for stored information without making a new one, but can't edit them without making a new one?
Or am I understanding that wrong?
Btw, I can see that you're iterating for (int i = 0; i < tso.TownSO.items.Count; i++) but you access tso.TownSO.itemStocks[i]. It may cause issues if the number of elements in both lists doesn't match. I would suggest creating a class/struct as a container to group an item and item stock in a single object, then create a list of such containers.
I was thinking something similar, i was told early on that having alot of instances of the same monoclass is taxing and unadvisable so I was attempting to make a work around using scriptable objects as I know they're slightly less taxing
Although all I managed to do was confuse myself and make an overall more taxing system haha
To simplify:
- Class field stores a reference to a class object. If you assign the same class to multiple fields, all fields will reference the same class.
- Struct field stores object value. If you assign the same struct to multiple fields, each field will have a unique instance of that struct.
Structs take less space and tend to be more performant, but passing them around is a bit annoying.
I see, although it seems if I wanted to make individual merchants all built from a "merchant" struct that would actually be better then having them as scriptable objects as it's easier to call information from a struct
I would say that having a lot of instances of the same class isn't an issue, as long as it doesn't duplicate your data. For example, if every merchant had the same economy settings that contain a lot of data, then instead of storing a copy of these settings, it would be better to store a reference to a single settings preset.
That makes sense, so anything that would always stay constant should be in a separate reference while things that differ can be linked to the individual using a separate class or struct
I should've thought about it like that to begin with, I was so focused on making scriptable objects work that I didn't think about why I shouldn't have been