OFERTA Oferta = Stock + prod.Jugador Stock = prod....
Creado el: 26 de febrero de 2025
Creado el: 26 de febrero de 2025
OFERTA
Oferta = Stock + prod.Jugador
Stock = prod.NPC1 + prod.NPC2 + prod.NPC3
(ejemplo, mp = materia prima, Δ = numero aleatorio dentro de un rango (positivo o negativo))
prod.NPC1:
mp1 = x +- Δ
mp2 = y +- Δ
mp3 = z +- Δ
prod.Jugador = produccion x ciclo
DEMANDA
Demanda (para cada mp) = consumidores +- Δ1
consumidores = %poblacionTotal
poblacionTotal = poblacionAnterior +- Δ2
Δ1 = (eventos aleatorios) +- (temporada (invierno, verano...))
Δ2 = (eventos aleatorios) +- (temporada) +- Δ3
Δ3 = numero aleatorio (positivo o negativo) dentro de un rango
PRECIOS FINALES
precioMercado = precioBase x (1 + α x (Demanda - Oferta))
α = 0,1 (puede variar)
precioBase = depende de la materia prima.
como puedo implementar este sistema en mi juego Tycoon en unity? determina el precio de mercado de cada recurso cada 30 segundos (o "ciclo", ya que tengo un script que maneja cada ciclo y su duracion) en tres scripts si es posible (Demanda, Oferta y Precios). La cantidad de materias primas producidas por el jugador estan declaradas en otro script aparte que ya tengo (llamemosle "Recursos")
A continuación te propongo una forma de estructurar el sistema en tres scripts separados (Demanda, Oferta y Precios) más un pequeño “manager” que se encargue de orquestar el cálculo cada 30 segundos (o cada ciclo). Ten en cuenta que este es solo un ejemplo orientativo y puedes adaptarlo a tus necesidades concretas (por ejemplo, usar ScriptableObjects en lugar de MonoBehaviours, usar un único GameManager que agrupe todo, etc.).
Demanda:
Oferta:
Recursos
).Precios:
Actualización cada ciclo (30s):
Coroutine
) con WaitForSeconds(30)
, un InvokeRepeating
, o un temporizador manual.csharpusing UnityEngine; public class DemandManager : MonoBehaviour { // Demandas calculadas para cada materia prima. // Supongamos que tienes 3 materias primas: mp1, mp2, mp3 public float demandaMp1 { get; private set; } public float demandaMp2 { get; private set; } public float demandaMp3 { get; private set; } // Parámetros que influyen en la demanda [Header("Población")] public float poblacionActual = 1000f; // Se puede inicializar a un valor base public float porcentajeConsumidores = 0.5f; // Ej: 50% de la población consume la materia [Header("Rangos de variación aleatoria")] public Vector2 deltaPoblacion = new Vector2(-20f, 20f); // Variación de la población public Vector2 deltaDemanda = new Vector2(-10f, 10f); // Variación de la demanda final [Header("Ajustes estacionales/eventos")] public float factorInvierno = -0.1f; // -10% de la demanda public float factorVerano = 0.2f; // +20% de la demanda // ...y podrías tener otros factores u otros tipos de evento // Ejemplo simple para definir la temporada actual public enum Temporada { None, Invierno, Verano } public Temporada temporadaActual = Temporada.None; /// <summary> /// Método principal para calcular la demanda de cada recurso. /// Lo puedes llamar cada ciclo. /// </summary> public void CalcularDemanda() { // 1. Calcular población con variaciones aleatorias float variacionPoblacion = Random.Range(deltaPoblacion.x, deltaPoblacion.y); poblacionActual += variacionPoblacion; // Evitar población negativa, por si acaso if (poblacionActual < 0) poblacionActual = 0; // 2. Calcula la base de consumidores float baseConsumidores = poblacionActual * porcentajeConsumidores; // 3. Ajuste por temporada (opcional) float factorEstacional = 0f; switch (temporadaActual) { case Temporada.Invierno: factorEstacional = factorInvierno; break; case Temporada.Verano: factorEstacional = factorVerano; break; } // 4. Variación de la demanda (evento aleatorio) float variacionDemanda = Random.Range(deltaDemanda.x, deltaDemanda.y); // 5. Demanda final por recurso (puedes personalizar por recurso) demandaMp1 = (baseConsumidores + variacionDemanda) * (1 + factorEstacional); demandaMp2 = (baseConsumidores + variacionDemanda) * (1 + factorEstacional); demandaMp3 = (baseConsumidores + variacionDemanda) * (1 + factorEstacional); // Si quieres evitar demandas negativas: demandaMp1 = Mathf.Max(demandaMp1, 0); demandaMp2 = Mathf.Max(demandaMp2, 0); demandaMp3 = Mathf.Max(demandaMp3, 0); // Aquí podrías mostrarlo en consola para pruebas Debug.Log($"Demanda calculada -> mp1: {demandaMp1}, mp2: {demandaMp2}, mp3: {demandaMp3}"); } }
Notas:
csharpusing UnityEngine; public class SupplyManager : MonoBehaviour { // Oferta total calculada public float ofertaMp1 { get; private set; } public float ofertaMp2 { get; private set; } public float ofertaMp3 { get; private set; } [Header("NPC Production Ranges")] public Vector2 npc1Mp1Range = new Vector2(10, 20); // Podría ser x +- Δ public Vector2 npc1Mp2Range = new Vector2(5, 15); public Vector2 npc1Mp3Range = new Vector2(1, 5); public Vector2 npc2Mp1Range = new Vector2(8, 25); public Vector2 npc2Mp2Range = new Vector2(5, 10); public Vector2 npc2Mp3Range = new Vector2(2, 6); public Vector2 npc3Mp1Range = new Vector2(7, 12); public Vector2 npc3Mp2Range = new Vector2(6, 18); public Vector2 npc3Mp3Range = new Vector2(3, 7); // Referencia a tu script de Recursos donde está la producción del jugador // Asumamos que en "Recursos" tienes propiedades: produccionMp1, produccionMp2, produccionMp3 public Recursos recursosDelJugador; public void CalcularOferta() { // 1. Calcular Stock (suma de producciones de NPC) float npc1Mp1 = Random.Range(npc1Mp1Range.x, npc1Mp1Range.y); float npc1Mp2 = Random.Range(npc1Mp2Range.x, npc1Mp2Range.y); float npc1Mp3 = Random.Range(npc1Mp3Range.x, npc1Mp3Range.y); float npc2Mp1 = Random.Range(npc2Mp1Range.x, npc2Mp1Range.y); float npc2Mp2 = Random.Range(npc2Mp2Range.x, npc2Mp2Range.y); float npc2Mp3 = Random.Range(npc2Mp3Range.x, npc2Mp3Range.y); float npc3Mp1 = Random.Range(npc3Mp1Range.x, npc3Mp1Range.y); float npc3Mp2 = Random.Range(npc3Mp2Range.x, npc3Mp2Range.y); float npc3Mp3 = Random.Range(npc3Mp3Range.x, npc3Mp3Range.y); float stockMp1 = npc1Mp1 + npc2Mp1 + npc3Mp1; float stockMp2 = npc1Mp2 + npc2Mp2 + npc3Mp2; float stockMp3 = npc1Mp3 + npc2Mp3 + npc3Mp3; // 2. Añadir producción del jugador // Asumiendo que en "Recursos" tienes algo como: recursosDelJugador.produccionMp1 ofertaMp1 = stockMp1 + recursosDelJugador.produccionMp1; ofertaMp2 = stockMp2 + recursosDelJugador.produccionMp2; ofertaMp3 = stockMp3 + recursosDelJugador.produccionMp3; Debug.Log($"Oferta calculada -> mp1: {ofertaMp1}, mp2: {ofertaMp2}, mp3: {ofertaMp3}"); } }
Notas:
Stock
= prod.NPC1 + prod.NPC2 + prod.NPC3
.npcXMpYRange
según tu necesidad (esas son las variaciones ±Δ).Recursos
(del jugador) a la variable recursosDelJugador
en el inspector.csharpusing UnityEngine; public class PriceManager : MonoBehaviour { [Header("Parámetros de Precios")] public float precioBaseMp1 = 10f; public float precioBaseMp2 = 20f; public float precioBaseMp3 = 5f; // Factor alfa (puede variar) public float alpha = 0.1f; // Precios finales public float precioMercadoMp1 { get; private set; } public float precioMercadoMp2 { get; private set; } public float precioMercadoMp3 { get; private set; } // Referencias a scripts de Demanda y Oferta public DemandManager demandManager; public SupplyManager supplyManager; public void CalcularPrecios() { // Usamos: precioMercado = precioBase * (1 + α * (Demanda - Oferta)) precioMercadoMp1 = precioBaseMp1 * (1 + alpha * (demandManager.demandaMp1 - supplyManager.ofertaMp1)); precioMercadoMp2 = precioBaseMp2 * (1 + alpha * (demandManager.demandaMp2 - supplyManager.ofertaMp2)); precioMercadoMp3 = precioBaseMp3 * (1 + alpha * (demandManager.demandaMp3 - supplyManager.ofertaMp3)); // Evitar valores negativos (opcional): precioMercadoMp1 = Mathf.Max(0.01f, precioMercadoMp1); precioMercadoMp2 = Mathf.Max(0.01f, precioMercadoMp2); precioMercadoMp3 = Mathf.Max(0.01f, precioMercadoMp3); Debug.Log($"Precios -> mp1: {precioMercadoMp1}, mp2: {precioMercadoMp2}, mp3: {precioMercadoMp3}"); } }
Notas:
Demanda - Oferta
es grande y positivo, sube el precio; si es negativo, baja el precio.alpha
controla la sensibilidad del precio a la diferencia entre Demanda y Oferta.Para finalizar, puedes tener un script que centralice la llamada a estos tres sistemas cada 30 segundos. Por ejemplo:
csharpusing UnityEngine; using System.Collections; public class MarketCycleManager : MonoBehaviour { public DemandManager demandManager; public SupplyManager supplyManager; public PriceManager priceManager; [Header("Duración de cada ciclo en segundos")] public float cycleDuration = 30f; private void Start() { // Comenzamos la corrutina que cada 'cycleDuration' segundos recalcula todo StartCoroutine(MarketCycleRoutine()); } private IEnumerator MarketCycleRoutine() { while (true) { // 1. Calcular la Demanda demandManager.CalcularDemanda(); // 2. Calcular la Oferta supplyManager.CalcularOferta(); // 3. Calcular Precios priceManager.CalcularPrecios(); // Esperamos el siguiente ciclo yield return new WaitForSeconds(cycleDuration); } } }
Notas:
DemandManager
, SupplyManager
y PriceManager
.InvokeRepeating("Metodo", 0, cycleDuration);
en lugar de corrutina.En tu script Recursos
(o como lo llames), debes asegurarte de tener las propiedades públicas (o getters) que las otras clases necesitan para leer la producción del jugador. Ejemplo:
csharpusing UnityEngine; public class Recursos : MonoBehaviour { public float produccionMp1 = 10f; public float produccionMp2 = 5f; public float produccionMp3 = 2f; // Aquí va tu lógica de cómo el jugador produce recursos, // por ejemplo usando edificios, trabajadores, etc. }
Después, en el Inspector de tu escena, arrastras el objeto que tenga el script Recursos
al campo recursosDelJugador
en el SupplyManager
.
DemandManager.CalcularDemanda()
-> Población se actualiza, factores estacionales y aleatorios, se obtiene la Demanda para cada recurso.SupplyManager.CalcularOferta()
-> Suma la producción del jugador (Recursos
) y la de NPCs (con sus variaciones aleatorias), se obtiene la Oferta.PriceManager.CalcularPrecios()
-> Con Demanda
y Oferta
ya calculadas, se genera el nuevo precio de mercado para cada recurso, usando la fórmula.De esta manera, mantienes tu código modular, fácil de depurar y extender. Luego podrás ajustar fácilmente los factores aleatorios, las fórmulas de demanda y oferta, y la manera en la que presentas la información al jugador.