OFERTA Oferta = Stock + prod.Jugador Stock = prod....
बनाया गया: 26 फ़रवरी 2025
बनाया गया: 26 फ़रवरी 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, asi que podemos invocar al script o su corrutina) 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 verás un ejemplo de cómo podrías estructurar tres scripts (Demanda, Oferta y Precios) para calcular el precio de mercado de cada recurso cada cierto intervalo de tiempo (ciclo). La idea principal es:
El flujo podría ser:
csharpusing UnityEngine; using System.Collections; public class DemandManager : MonoBehaviour { // Parámetros base (puedes ajustarlos según tu juego) [Header("Población")] public float poblacionBase = 1000f; // Población inicial public float poblacionActual; // Población que irá variando [Header("Valores de Demanda por Recurso")] // Suponiendo que tienes varios recursos, puedes usar un array o lista public float[] demandaRecursos; // Cada índice corresponde a un recurso distinto [Header("Parámetros de Ajuste")] public float variacionPoblacionMax = 50f; // Delta aleatorio para la población public float variacionDemandaMax = 10f; // Delta aleatorio para la demanda de cada recurso [Header("Factores Estacionales (Ejemplo)")] public float factorInvierno = -5f; public float factorVerano = 10f; // Puedes agregar otras estaciones o eventos private void Start() { // Inicializamos la población y la demanda poblacionActual = poblacionBase; demandaRecursos = new float[] { 100f, 120f, 80f }; // ... o configura la longitud/valores que necesites según tus recursos } public void CalcularDemanda() { // 1) Calcular población actual (poblacionAnterior +- Δ2) float deltaPoblacion = Random.Range(-variacionPoblacionMax, variacionPoblacionMax); // Ejemplo básico: puedes sumar también eventos o factores estacionales poblacionActual += deltaPoblacion; // Evita que baje de cero if (poblacionActual < 0) poblacionActual = 0; // 2) Calcular demanda para cada recurso for (int i = 0; i < demandaRecursos.Length; i++) { float deltaDemanda = Random.Range(-variacionDemandaMax, variacionDemandaMax); // Ajuste base por población // Asumimos que la demanda crece con la población float factorPoblacion = (poblacionActual / poblacionBase); // Factores estacionales (opcional) float factorEstacional = 0f; // Aquí podrías poner lógica: si es invierno, factorEstacional = factorInvierno, etc. // Por simplicidad, tomamos un ejemplo fijo: factorEstacional = factorInvierno; // si estamos en invierno, por ejemplo // Demanda nueva demandaRecursos[i] = demandaRecursos[i] * factorPoblacion + deltaDemanda + factorEstacional; // Evita valores negativos if (demandaRecursos[i] < 0) demandaRecursos[i] = 0; } } }
CalcularDemanda()
se invocará desde un manager o corrutina cada vez que quieras actualizar la demanda (cada 30 s, por ejemplo).csharpusing UnityEngine; public class SupplyManager : MonoBehaviour { [Header("Producción Jugador (Referencia a otro Script)")] public Recursos recursosJugador; // Asumiendo que "Recursos" es tu script con la producción del jugador [Header("Producción NPCs / Externos")] public float[] produccionNPCs; // Producción total de NPCs para cada recurso [Header("Stock / Oferta Total")] public float[] ofertaRecursos; [Header("Parámetros de Variación de NPCs")] public float variacionNPCMax = 5f; // Delta aleatorio (+/-) private void Start() { // Inicializa en base a la cantidad de recursos que tengas // Deben coincidir los tamaños de ofertaRecursos, produccionNPCs y los arrays del script Recursos ofertaRecursos = new float[] { 0f, 0f, 0f }; produccionNPCs = new float[] { 50f, 40f, 30f }; } public void CalcularOferta() { // 1) Actualiza la producción de NPCs con alguna variación for (int i = 0; i < produccionNPCs.Length; i++) { float delta = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPCs[i] += delta; if (produccionNPCs[i] < 0) produccionNPCs[i] = 0; // Evitar negativos } // 2) Sumar la producción del jugador + la de NPCs para obtener la oferta for (int i = 0; i < ofertaRecursos.Length; i++) { // recursosJugador.cantidadProducida[i] es la producción del jugador para el recurso i ofertaRecursos[i] = produccionNPCs[i] + recursosJugador.cantidadProducida[i]; } } }
CalcularOferta()
se llamará también cada ciclo (cada 30 s).Aquí calculamos el precio final de cada recurso usando la fórmula:
csharpusing UnityEngine; public class PriceManager : MonoBehaviour { [Header("Referencias a otros Scripts")] public DemandManager demandManager; public SupplyManager supplyManager; [Header("Parámetros de Precios")] public float alpha = 0.1f; // Factor de ajuste (α = 0.1) public float[] precioBase; // Precio base de cada recurso [Header("Precio Resultante")] public float[] precioMercado; // Precio que se recalcula cada ciclo private void Start() { // Asegúrate de que coincida con la cantidad de recursos precioBase = new float[] { 5f, 8f, 3f }; precioMercado = new float[precioBase.Length]; } public void CalcularPrecios() { for (int i = 0; i < precioBase.Length; i++) { float demanda = demandManager.demandaRecursos[i]; float oferta = supplyManager.ofertaRecursos[i]; float factor = 1f + alpha * (demanda - oferta); // Evitar que el factor baje de 0, para no tener precios negativos if (factor < 0) factor = 0; // precioMercado = precioBase * factor precioMercado[i] = precioBase[i] * factor; } } }
DemandManager
y la oferta del SupplyManager
.(1 + α * (Demanda - Oferta))
.precioMercado[i]
para cada recurso.Para hacer que estos cálculos se realicen cada 30 segundos, podrías tener un GameManager o un script central que controle los ciclos. Por ejemplo:
csharpusing UnityEngine; using System.Collections; public class GameManager : MonoBehaviour { public DemandManager demandManager; public SupplyManager supplyManager; public PriceManager priceManager; [Header("Duración de cada ciclo en segundos")] public float duracionCiclo = 30f; private void Start() { // Inicia la corrutina de ciclos StartCoroutine(CicloEconomico()); } private IEnumerator CicloEconomico() { while (true) { // Esperamos el tiempo designado yield return new WaitForSeconds(duracionCiclo); // 1) Calcular demanda demandManager.CalcularDemanda(); // 2) Calcular oferta supplyManager.CalcularOferta(); // 3) Calcular precios priceManager.CalcularPrecios(); // Aquí podrías notificar a otros sistemas que usen los precios // Por ejemplo, actualizar una UI, etc. } } }
GameManager
inicia la corrutina CicloEconomico()
.duracionCiclo
segundos (por defecto 30), se llama:
demandManager.CalcularDemanda();
supplyManager.CalcularOferta();
priceManager.CalcularPrecios();
priceManager.precioMercado
.Recursos (Producción del Jugador): Asegúrate de que tu script Recursos
tenga algo como:
csharppublic class Recursos : MonoBehaviour { public float[] cantidadProducida; // Producción actual para cada recurso // Aquí tendrías lógica para producir recursos con el tiempo, // o métodos que incrementen la producción según mejoras en el Tycoon, etc. }
Luego, en SupplyManager, asignas esta referencia en el Inspector para que SupplyManager
pueda leer recursosJugador.cantidadProducida[i]
.
Control de Límites: En todos los cálculos (población, demanda, oferta, precios), conviene asegurarse de no generar números negativos o imposibles.
Escalabilidad: Si tienes muchos recursos, podrías usar un ScriptableObject
para configurarlos o incluso una base de datos.
Eventos / Temporadas: Puedes ampliar la lógica de demanda u oferta para que factores estacionales o eventos (festividades, crisis, etc.) sumen o resten una cantidad específica y no solo sea aleatorio.
Con esta estructura modular:
De esta manera tienes el sistema de economía funcionando de forma ordenada y fácil de mantener. ¡Ya solo quedaría ajustarlo a la lógica específica de tu juego Tycoon!
script de recursos de mi juego:
using UnityEngine;
public class recursos : MonoBehaviour
{
// materias primas
public int mP1 = 0;
public int mP2 = 0;
public int mP3 = 0;
public int mP4 = 0;
public int mP5 = 0;
public int mP6 = 0;
public int mP7 = 0;
public int mP8 = 0;
public int mP9 = 0;
textpublic int capacidadMP1 = 0; public int capacidadMP2 = 0; public int capacidadMP3 = 0; // bienes manufacturados public int bM1 = 0; public int bM2 = 0; public int bM3 = 0; public int bM4 = 0; public int bM5 = 0; public int bM6 = 0; // puntuación total del jugador public float dinero = 0f; public float conocimiento = 0f; public float fuerzaMilitar = 0f; // incremento de materias primas public void aumentarMP1(int cantidad) { mP1 = Mathf.Min(mP1 + cantidad, capacidadMP1); Debug.Log("Granos totales = " + mP1 + " / " + capacidadMP1); } public void aumentarMP2(int cantidad) { mP2 = Mathf.Min(mP2 + cantidad, capacidadMP2); Debug.Log("Hortalizas totales = " + mP2 + " / " + capacidadMP2); } public void aumentarMP3(int cantidad) { mP3 = Mathf.Min(mP3 + cantidad, capacidadMP3); Debug.Log("Frutas totales = " + mP3 + " / " + capacidadMP3); }
}
script de ciclos, lo mejor es que se invoque en Game Manager en vez de crear otra corrutina.
using UnityEngine;
using System.Collections;
using System;
public class ciclos : MonoBehaviour
{
// ciclo productivo
textpublic event Action onCicloCompleto; public float cicloProductivo = 15f; public int ciclosTotales = 0; private Coroutine cicloCorrutina; void Start() { cicloCorrutina = StartCoroutine(ciclosContador()); } IEnumerator ciclosContador() { while (true) { yield return new WaitForSeconds(cicloProductivo); ciclosTotales += 1; Debug.Log("Ciclo completado. Ciclos totales: " + ciclosTotales); onCicloCompleto.Invoke(); } } void OnDisable() { StopCoroutine(cicloCorrutina); }
}
ajusta o corrige los scripts que me proporcionas en base a esto
A continuación verás una versión ajustada de los tres scripts (Demanda, Oferta, Precios) teniendo en cuenta:
mP1
…mP9
, etc.).onCicloCompleto
cada vez que termina un ciclo productivo.GameManager
(o script central) que reciba la notificación de onCicloCompleto
.La idea es:
recursos
) y la producción de NPC (o productores externos).Finalmente, un GameManager central se suscribirá al evento onCicloCompleto
del script ciclos
y, en cada ciclo, invocará los métodos de demanda, oferta y precios.
csharpusing UnityEngine; public class DemandManager : MonoBehaviour { [Header("Parámetros Población")] public float poblacionBase = 1000f; public float poblacionActual = 1000f; [Header("Demanda por cada MP (9 Materias Primas)")] public float[] demandaRecursos = new float[9]; [Header("Rangos de variación")] public float variacionPoblacionMax = 50f; public float variacionDemandaMax = 10f; [Header("Factores Estacionales (Ejemplo)")] public float factorInvierno = -5f; public float factorVerano = 10f; // Ajusta esto si deseas más control sobre la temporada actual. // Por ejemplo, podrías crear un enum Temporada { Invierno, Verano, Otoño, Primavera } // y asignar un factor distinto según la estación. // Aquí lo dejaremos fijo como ejemplo. public bool esInvierno = true; private void Start() { // Valores iniciales de demanda (puedes cambiarlos según tu diseño) for (int i = 0; i < demandaRecursos.Length; i++) { demandaRecursos[i] = 50f + (i * 5f); } } /// <summary> /// Llamar en cada ciclo para recalcular la demanda. /// </summary> public void CalcularDemanda() { // 1) Ajustar población float deltaPoblacion = Random.Range(-variacionPoblacionMax, variacionPoblacionMax); poblacionActual += deltaPoblacion; if (poblacionActual < 0) poblacionActual = 0; // 2) Calcular demanda base para cada recurso float factorPoblacion = (poblacionActual / poblacionBase); // Ejemplo de factor estacional float factorEstacional = esInvierno ? factorInvierno : factorVerano; for (int i = 0; i < demandaRecursos.Length; i++) { float deltaDemanda = Random.Range(-variacionDemandaMax, variacionDemandaMax); // Nueva demanda = (demanda base anterior * factor población) + variación aleatoria + estacional float nuevaDemanda = demandaRecursos[i] * factorPoblacion + deltaDemanda + factorEstacional; // Evitar que caiga por debajo de 0 if (nuevaDemanda < 0) nuevaDemanda = 0; demandaRecursos[i] = nuevaDemanda; } // Debug opcional Debug.Log("Demanda recalculada. Ej: Demanda MP1 = " + demandaRecursos[0]); } }
demandaRecursos
.CalcularDemanda()
.csharpusing UnityEngine; public class SupplyManager : MonoBehaviour { [Header("Referencia al script 'recursos' (Producción del Jugador)")] public recursos recursosJugador; // Asigna en el Inspector [Header("Producción NPC (o externos) para 9 MP")] public float[] produccionNPCs = new float[9]; [Header("Oferta final (se recalcula cada ciclo)")] public float[] ofertaRecursos = new float[9]; [Header("Variación máxima NPC por ciclo")] public float variacionNPCMax = 5f; private void Start() { // Inicializamos con algún valor base for(int i = 0; i < produccionNPCs.Length; i++) { produccionNPCs[i] = 50f + (i * 5f); } } /// <summary> /// Llamar en cada ciclo para recalcular la oferta total. /// </summary> public void CalcularOferta() { // 1) Variación aleatoria en producción NPC for (int i = 0; i < produccionNPCs.Length; i++) { float delta = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPCs[i] += delta; if (produccionNPCs[i] < 0) produccionNPCs[i] = 0; } // 2) Sumamos la producción del jugador // Tu script 'recursos' tiene mP1... mP9 como ENTEROS. // Asumamos que la "oferta" del jugador es simplemente la cantidad actual de cada mP que posee. // En un juego Tycoon más complejo podrías querer: // "oferta del jugador = lo que produce por ciclo" // en vez de la cantidad total que tiene almacenada. // Pero aquí lo tomaremos como "lo que posee" = su oferta disponible. // OJO: Ajusta esta lógica si necesitas un sistema distinto. // Construimos un array con las 9 MPs del jugador int[] mpJugador = new int[] { recursosJugador.mP1, recursosJugador.mP2, recursosJugador.mP3, recursosJugador.mP4, recursosJugador.mP5, recursosJugador.mP6, recursosJugador.mP7, recursosJugador.mP8, recursosJugador.mP9 }; for (int i = 0; i < ofertaRecursos.Length; i++) { // Oferta total = Producción NPC + (lo que el jugador posee) // Convertimos int del jugador a float (por si se usa en la fórmula) ofertaRecursos[i] = produccionNPCs[i] + mpJugador[i]; } // Debug opcional Debug.Log("Oferta recalculada. Ej: Oferta MP1 = " + ofertaRecursos[0]); } }
recursos
(recursosJugador
).ofertaRecursos
contendrá la oferta total final (NPC + jugador).csharpusing UnityEngine; public class PriceManager : MonoBehaviour { [Header("Referencias")] public DemandManager demandManager; public SupplyManager supplyManager; [Header("Parámetros de Precios")] public float alpha = 0.1f; // Factor α public float[] precioBase = new float[9]; // Precio base para cada una de las 9 materias primas [Header("Precios de Mercado (Salida)")] public float[] precioMercado = new float[9]; // Resultado final private void Start() { // Inicializamos precios base // Ajusta estos valores según tu diseño for(int i = 0; i < precioBase.Length; i++) { precioBase[i] = 5f + (i * 2f); } } /// <summary> /// Llamar en cada ciclo después de calcular Demanda y Oferta. /// </summary> public void CalcularPrecios() { for (int i = 0; i < precioBase.Length; i++) { float demanda = demandManager.demandaRecursos[i]; float oferta = supplyManager.ofertaRecursos[i]; // Factor = 1 + α * (Demanda - Oferta) float factor = 1f + alpha * (demanda - oferta); // Evitamos precios negativos if (factor < 0) factor = 0; precioMercado[i] = precioBase[i] * factor; } // Debug opcional Debug.Log("Precio MP1 = " + precioMercado[0]); } }
demandaRecursos
y ofertaRecursos
.precioMercado
se almacena con el resultado final.Debido a que no quieres usar otra corrutina, sino aprovechar el evento onCicloCompleto
del script ciclos
, podemos crear un GameManager
(o cualquier script) que se suscriba a dicho evento.
Pasos:
DemandManager
, SupplyManager
, PriceManager
, ciclos
) a un objeto en la escena (por ejemplo, un GameManager
vacío).onCicloCompleto
en el Start()
de tu GameManager
.Ejemplo de GameManager:
csharpusing UnityEngine; public class GameManager : MonoBehaviour { [Header("Referencias")] public ciclos ciclosScript; // Asigna en el Inspector, es tu script de ciclos public DemandManager demandManager; public SupplyManager supplyManager; public PriceManager priceManager; private void Start() { // Suscribirse al evento de ciclo if (ciclosScript != null) { ciclosScript.onCicloCompleto += OnCicloCompletoHandler; } } private void OnDestroy() { // Por si este objeto se destruye, desuscribirse if (ciclosScript != null) { ciclosScript.onCicloCompleto -= OnCicloCompletoHandler; } } /// <summary> /// Método que se llama cada vez que el evento onCicloCompleto (de 'ciclos') se dispare. /// </summary> private void OnCicloCompletoHandler() { // 1) Calcular demanda demandManager.CalcularDemanda(); // 2) Calcular oferta supplyManager.CalcularOferta(); // 3) Calcular precios priceManager.CalcularPrecios(); // Aquí podrías hacer otras cosas, como actualizar UI, comprobar stocks, etc. Debug.Log("¡Ciclo completo! Se han recalculado Demanda, Oferta y Precios."); } }
ciclos
tiene un yield return new WaitForSeconds(cicloProductivo);
y al finalizar invoca onCicloCompleto.Invoke()
.GameManager
recibe ese evento (en OnCicloCompletoHandler()
), y llama en orden a CalcularDemanda()
, CalcularOferta()
y CalcularPrecios()
.priceManager.precioMercado[i]
.ciclos
se mantiene como está, con su onCicloCompleto
.GameManager
que se suscriba al evento de ciclos y haga la llamada a los métodos de cálculo en cada ciclo.recursos
provee la cantidad de materias primas del jugador, que en este ejemplo se asume como parte de la Oferta.Ajusta los valores iniciales, las fórmulas, la forma en que se calculan las estacionalidades y la lógica de “cuánto produce el jugador” de acuerdo con la mecánica exacta de tu Tycoon.
Con esto tienes la base del sistema de economía que se actualiza automáticamente cada vez que finaliza un ciclo.
la i en los arrays simbolizan el numero de posicion de una variable? perdon, se muy poco de programacion
En C# (y en muchos otros lenguajes), cuando usamos un bucle for (int i = 0; i < array.Length; i++)
, la variable i
es simplemente un índice que va recorriendo las posiciones (o “casillas”) de ese array, empezando normalmente en cero y terminando en array.Length - 1
.
array[0]
se refiere a la primera posición del array.array[1]
se refiere a la segunda posición.array[array.Length - 1]
que es la última posición.Por ejemplo, si tienes un array public float[] miArray = new float[5];
, tendrás 5 posiciones internas (índices 0, 1, 2, 3 y 4). Cuando haces:
csharpfor (int i = 0; i < miArray.Length; i++) { // Aquí i toma valores: 0, 1, 2, 3, 4 // y puedes acceder a miArray[i] }
i = 0
→ miArray[0]
i = 1
→ miArray[1]
Entonces, usar array[i]
en un bucle for
te permite recorrer (o “iterar”) todos los elementos del array sin tener que escribir una línea de código para cada posición.
un apunte, me gustaria que en el siguiente script:
using UnityEngine;
public class SupplyManager : MonoBehaviour
{
[Header("Referencia al script 'recursos' (Producción del Jugador)")]
public recursos recursosJugador; // Asigna en el Inspector
text[Header("Producción NPC (o externos) para 9 MP")] public float[] produccionNPCs = new float[9]; [Header("Oferta final (se recalcula cada ciclo)")] public float[] ofertaRecursos = new float[9]; [Header("Variación máxima NPC por ciclo")] public float variacionNPCMax = 5f; private void Start() { // Inicializamos con algún valor base for(int i = 0; i < produccionNPCs.Length; i++) { produccionNPCs[i] = 50f + (i * 5f); } } /// <summary> /// Llamar en cada ciclo para recalcular la oferta total. /// </summary> public void CalcularOferta() { // 1) Variación aleatoria en producción NPC for (int i = 0; i < produccionNPCs.Length; i++) { float delta = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPCs[i] += delta; if (produccionNPCs[i] < 0) produccionNPCs[i] = 0; } // 2) Sumamos la producción del jugador // Tu script 'recursos' tiene mP1... mP9 como ENTEROS. // Asumamos que la "oferta" del jugador es simplemente la cantidad actual de cada mP que posee. // En un juego Tycoon más complejo podrías querer: // "oferta del jugador = lo que produce por ciclo" // en vez de la cantidad total que tiene almacenada. // Pero aquí lo tomaremos como "lo que posee" = su oferta disponible. // OJO: Ajusta esta lógica si necesitas un sistema distinto. // Construimos un array con las 9 MPs del jugador int[] mpJugador = new int[] { recursosJugador.mP1, recursosJugador.mP2, recursosJugador.mP3, recursosJugador.mP4, recursosJugador.mP5, recursosJugador.mP6, recursosJugador.mP7, recursosJugador.mP8, recursosJugador.mP9 }; for (int i = 0; i < ofertaRecursos.Length; i++) { // Oferta total = Producción NPC + (lo que el jugador posee) // Convertimos int del jugador a float (por si se usa en la fórmula) ofertaRecursos[i] = produccionNPCs[i] + mpJugador[i]; } // Debug opcional Debug.Log("Oferta recalculada. Ej: Oferta MP1 = " + ofertaRecursos[0]); }
}
se especifique no solo la produccion de los NPCs de todas las materias primas, sino que haya 3 npc que tengan producciones diferentes sobre cada una de las 9 materias primas
A continuación tienes un ejemplo donde hay 3 NPCs distintos, cada uno con su propia producción de las 9 materias primas. Luego, se suma todo para obtener la oferta total (NPC1 + NPC2 + NPC3 + jugador).
csharpusing UnityEngine; public class SupplyManager : MonoBehaviour { [Header("Referencia al script 'recursos' (Producción del Jugador)")] public recursos recursosJugador; // Asigna en el Inspector [Header("Producción de cada NPC (3 NPCs, 9 MP)")] public float[] produccionNPC1 = new float[9]; public float[] produccionNPC2 = new float[9]; public float[] produccionNPC3 = new float[9]; [Header("Oferta final (se recalcula cada ciclo)")] public float[] ofertaRecursos = new float[9]; [Header("Variación máxima NPC por ciclo")] public float variacionNPCMax = 5f; private void Start() { // Iniciamos valores base para cada NPC // (ajusta estos valores según la lógica de tu juego) for (int i = 0; i < 9; i++) { produccionNPC1[i] = 50f + (i * 5f); // Ejemplo: NPC1 produccionNPC2[i] = 40f + (i * 3f); // Ejemplo: NPC2 produccionNPC3[i] = 30f + (i * 2f); // Ejemplo: NPC3 } } /// <summary> /// Se llama cada ciclo para recalcular la oferta total. /// </summary> public void CalcularOferta() { // 1) Variación aleatoria para cada NPC for (int i = 0; i < 9; i++) { float delta1 = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPC1[i] += delta1; if (produccionNPC1[i] < 0) produccionNPC1[i] = 0; float delta2 = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPC2[i] += delta2; if (produccionNPC2[i] < 0) produccionNPC2[i] = 0; float delta3 = Random.Range(-variacionNPCMax, variacionNPCMax); produccionNPC3[i] += delta3; if (produccionNPC3[i] < 0) produccionNPC3[i] = 0; } // 2) Tomamos la cantidad actual del jugador (mP1..mP9) como su oferta int[] mpJugador = new int[] { recursosJugador.mP1, recursosJugador.mP2, recursosJugador.mP3, recursosJugador.mP4, recursosJugador.mP5, recursosJugador.mP6, recursosJugador.mP7, recursosJugador.mP8, recursosJugador.mP9 }; // 3) Sumar las producciones de NPC1, NPC2, NPC3 y el jugador for (int i = 0; i < 9; i++) { // Convertimos lo que tiene el jugador a float para sumarlo con la producción NPC ofertaRecursos[i] = produccionNPC1[i] + produccionNPC2[i] + produccionNPC3[i] + mpJugador[i]; } // Mensaje de ejemplo Debug.Log("Oferta recalculada. Ej: Oferta MP1 = " + ofertaRecursos[0]); } }
produccionNPC1
, produccionNPC2
, produccionNPC3
), cada uno para las 9 materias primas.Start()
, se inicializan con valores diferentes para cada NPC (puedes cambiarlo según tu juego).CalcularOferta()
:
±variacionNPCMax
a cada materia prima de cada NPC.recursos
).ofertaRecursos[i]
.Al final de cada ciclo, cuando llamas a este método, tu variable ofertaRecursos
quedará actualizada con la oferta total de las 9 materias primas.
y si tengo ya un valor fijo de produccion de cada materia prima para cada npc?
por ejemplo, el npc 1 produce 12 de mp1 x ciclo, 5 mp2 x ciclo, 1 mp3 x ciclo, etc. y para cada produccion una variacion diferente, y asi con los dos npc que siguen
A continuación verás un ejemplo de cómo podrías fijar la producción base de cada NPC para cada materia prima, y luego aplicar una variación diferente para cada producción (por recurso). Finalmente, se suman las producciones de los 3 NPCs y lo que el jugador tenga disponible para llegar a la oferta total.
csharpusing UnityEngine; public class SupplyManager : MonoBehaviour { [Header("Referencia al script 'recursos' (Producción del Jugador)")] public recursos recursosJugador; // Asigna en el Inspector [Header("Oferta final (se recalcula cada ciclo)")] public float[] ofertaRecursos = new float[9]; // -------------------------------------------------------------------------------- // A) PRODUCCIÓN BASE DE CADA NPC (por ciclo), para las 9 materias primas. // (Ajusta los valores a la lógica de tu juego) // -------------------------------------------------------------------------------- private float[] baseProdNPC1 = new float[9] { 12, 5, 1, 0, 10, 2, 3, 4, 6 }; private float[] baseProdNPC2 = new float[9] { 8, 3, 2, 2, 5, 1, 0, 3, 4 }; private float[] baseProdNPC3 = new float[9] { 10, 7, 1, 1, 3, 4, 2, 2, 1 }; // -------------------------------------------------------------------------------- // B) VARIACIÓN MÁXIMA PARA CADA MATERIA PRIMA, POR NPC // Esto te permite, por ejemplo, dar una variación ±2 en MP1, ±1 en MP2... // -------------------------------------------------------------------------------- private float[] varMaxNPC1 = new float[9] { 2f, 1f, 0.5f, 0f, 2f, 1f, 1f, 0.5f, 2f }; private float[] varMaxNPC2 = new float[9] { 1f, 2f, 1f, 0.5f, 3f, 1f, 0f, 2f, 1f }; private float[] varMaxNPC3 = new float[9] { 2f, 3f, 1f, 2f, 2f, 3f, 1f, 1f, 2f }; // -------------------------------------------------------------------------------- // C) PRODUCCIÓN REAL DE LOS NPC EN ESTE CICLO (se actualizará cada ciclo) // -------------------------------------------------------------------------------- [Header("Producción calculada cada ciclo para cada NPC")] public float[] produccionNPC1 = new float[9]; public float[] produccionNPC2 = new float[9]; public float[] produccionNPC3 = new float[9]; private void Start() { // Si deseas inicializar los arrays produccionNPC con algún valor inicial, // podrías copiar la base en Start(); aunque no es estrictamente necesario, // ya que en cada ciclo se recalculará. for (int i = 0; i < 9; i++) { produccionNPC1[i] = baseProdNPC1[i]; produccionNPC2[i] = baseProdNPC2[i]; produccionNPC3[i] = baseProdNPC3[i]; } } /// <summary> /// Llamar en cada ciclo para recalcular la oferta total. /// </summary> public void CalcularOferta() { // 1) Calcular la producción final de cada NPC (base ± variación) for (int i = 0; i < 9; i++) { // NPC1 float delta1 = Random.Range(-varMaxNPC1[i], varMaxNPC1[i]); produccionNPC1[i] = baseProdNPC1[i] + delta1; if (produccionNPC1[i] < 0) produccionNPC1[i] = 0; // Evitar negativos // NPC2 float delta2 = Random.Range(-varMaxNPC2[i], varMaxNPC2[i]); produccionNPC2[i] = baseProdNPC2[i] + delta2; if (produccionNPC2[i] < 0) produccionNPC2[i] = 0; // NPC3 float delta3 = Random.Range(-varMaxNPC3[i], varMaxNPC3[i]); produccionNPC3[i] = baseProdNPC3[i] + delta3; if (produccionNPC3[i] < 0) produccionNPC3[i] = 0; } // 2) Leemos la cantidad actual del jugador (mP1..mP9) como "lo que el jugador ofrece" int[] mpJugador = new int[] { recursosJugador.mP1, recursosJugador.mP2, recursosJugador.mP3, recursosJugador.mP4, recursosJugador.mP5, recursosJugador.mP6, recursosJugador.mP7, recursosJugador.mP8, recursosJugador.mP9 }; // 3) Sumamos la producción de NPC1, NPC2, NPC3 y la del jugador para obtener la oferta final for (int i = 0; i < 9; i++) { ofertaRecursos[i] = produccionNPC1[i] + produccionNPC2[i] + produccionNPC3[i] + mpJugador[i]; } // Debug opcional Debug.Log("Oferta recalculada. MP1 = " + ofertaRecursos[0] + ", MP2 = " + ofertaRecursos[1]); } }
Producción base:
baseProdNPC1
, baseProdNPC2
, baseProdNPC3
representan cuánto produce cada NPC de cada materia prima por ciclo, sin variaciones. Son arrays de 9 elementos (uno por cada MP).Variación máxima:
varMaxNPC1
, varMaxNPC2
, varMaxNPC3
almacenan la variación máxima por recurso para cada NPC.varMaxNPC1[0] = 2f
, significa que para la materia prima 1 (MP1), el NPC1 puede producir entre baseProdNPC1[0] - 2
y baseProdNPC1[0] + 2
.Producción calculada cada ciclo:
produccionNPC1[i]
= baseProdNPC1[i]
± Random.Range(...)
.ciclos
).Suma total (oferta):
ofertaRecursos[i]
= produccionNPC1[i] + produccionNPC2[i] + produccionNPC3[i] + mpJugador[i]
.mpJugador[i]
es la cantidad que el jugador tiene (o produce) para la materia prima i
.Evitar valores negativos:
if (produccionNPCx[i] < 0) produccionNPCx[i] = 0;
después de añadir la variación. Así no te quedas con producciones negativas.Uso en el juego:
GameManager
o donde uses el evento de tu script ciclos
, llama a supplyManager.CalcularOferta()
en cada ciclo (después o antes de calcular la demanda, según tu lógica).GameManager
:csharppublic class GameManager : MonoBehaviour { public ciclos ciclosScript; // Asigna en Inspector public SupplyManager supplyManager; // Asigna en Inspector // (También DemandManager, PriceManager, etc. si los tienes) private void Start() { // Suscripción al evento ciclosScript.onCicloCompleto += OnCicloCompletoHandler; } private void OnDestroy() { ciclosScript.onCicloCompleto -= OnCicloCompletoHandler; } private void OnCicloCompletoHandler() { // Llamamos a CalcularOferta() cada vez que finaliza un ciclo supplyManager.CalcularOferta(); // ... y luego, por ejemplo, DemandManager.CalcularDemanda() // ... y PriceManager.CalcularPrecios() Debug.Log("Ciclo completo: Oferta recalculada."); } }
De esta forma, cada vez que se complete el ciclo productivo (tu script ciclos
hace onCicloCompleto.Invoke()
), obtendrás una nueva oferta actualizada con la producción de cada NPC (más la del jugador).
en el script de demanda:
using UnityEngine;
public class DemandManager : MonoBehaviour
{
[Header("Parámetros Población")]
public float poblacionBase = 1000f;
public float poblacionActual = 1000f;
text[Header("Demanda por cada MP (9 Materias Primas)")] public float[] demandaRecursos = new float[9]; [Header("Rangos de variación")] public float variacionPoblacionMax = 50f; public float variacionDemandaMax = 10f; [Header("Factores Estacionales (Ejemplo)")] public float factorInvierno = -5f; public float factorVerano = 10f; // Ajusta esto si deseas más control sobre la temporada actual. // Por ejemplo, podrías crear un enum Temporada { Invierno, Verano, Otoño, Primavera } // y asignar un factor distinto según la estación. // Aquí lo dejaremos fijo como ejemplo. public bool esInvierno = true; private void Start() { // Valores iniciales de demanda (puedes cambiarlos según tu diseño) for (int i = 0; i < demandaRecursos.Length; i++) { demandaRecursos[i] = 50f + (i * 5f); } } /// <summary> /// Llamar en cada ciclo para recalcular la demanda. /// </summary> public void CalcularDemanda() { // 1) Ajustar población float deltaPoblacion = Random.Range(-variacionPoblacionMax, variacionPoblacionMax); poblacionActual += deltaPoblacion; if (poblacionActual < 0) poblacionActual = 0; // 2) Calcular demanda base para cada recurso float factorPoblacion = (poblacionActual / poblacionBase); // Ejemplo de factor estacional float factorEstacional = esInvierno ? factorInvierno : factorVerano; for (int i = 0; i < demandaRecursos.Length; i++) { float deltaDemanda = Random.Range(-variacionDemandaMax, variacionDemandaMax); // Nueva demanda = (demanda base anterior * factor población) + variación aleatoria + estacional float nuevaDemanda = demandaRecursos[i] * factorPoblacion + deltaDemanda + factorEstacional; // Evitar que caiga por debajo de 0 if (nuevaDemanda < 0) nuevaDemanda = 0; demandaRecursos[i] = nuevaDemanda; } // Debug opcional Debug.Log("Demanda recalculada. Ej: Demanda MP1 = " + demandaRecursos[0]); }
}
lo que requiero es que cada mp tenga una demanda distinta, donde los valores de demanda iniciales sean porcentajes diferentes segun la materia prima, y luego se le apliquen las variaciones de temporada, eventos y un numero aleatorio de forma distinta para cada mp. Recuerda:
Δ3 = numero aleatorio (positivo o negativo) dentro de un rango
A continuación encontrarás un ejemplo de cómo podrías estructurar tu DemandManager
para que cada materia prima (MP) tenga:
La lógica está inspirada en tu diagrama:
textDEMANDA para cada MP = consumidores ± Δ1 consumidores = %poblacionTotal poblacionTotal = poblacionAnterior ± Δ2 Δ1 = (eventos aleatorios) ± (temporada) Δ2 = (eventos aleatorios) ± (temporada) ± Δ3 Δ3 = número aleatorio dentro de un rango
Nota: Los nombres y valores son un ejemplo. Adáptalos a tu juego, ajustando los rangos y factores según tu diseño.
csharpusing UnityEngine; public class DemandManager : MonoBehaviour { [Header("=== Población ===")] [Tooltip("Población inicial")] public float poblacionActual = 1000f; [Tooltip("Variación aleatoria (eventos) mínima y máxima para la población")] public float minEventoPoblacion = -20f; public float maxEventoPoblacion = 20f; [Tooltip("Factor de temporada para la población (invierno)")] public float factorInviernoPoblacion = -10f; [Tooltip("Factor de temporada para la población (verano)")] public float factorVeranoPoblacion = 30f; [Tooltip("Rango para delta3 (población)")] public float minDelta3 = -10f; public float maxDelta3 = 10f; [Header("=== Demanda por cada MP (9 Materias Primas) ===")] public float[] demandaRecursos = new float[9]; [Tooltip("Porcentaje base de la población que demanda cada MP")] public float[] porcentajeBaseMP = new float[9] { 0.12f, // MP1 0.08f, // MP2 0.05f, // MP3 0.07f, // MP4 0.10f, // MP5 0.02f, // MP6 0.04f, // MP7 0.09f, // MP8 0.03f // MP9 }; [Tooltip("Variación aleatoria (eventos) mínima y máxima para cada MP")] public float minEventoDemanda = -5f; public float maxEventoDemanda = 5f; [Tooltip("Factor de temporada para la demanda (invierno)")] public float factorInviernoDemanda = -3f; [Tooltip("Factor de temporada para la demanda (verano)")] public float factorVeranoDemanda = 5f; [Header("=== Temporada Actual ===")] public bool esInvierno = true; void Start() { // (Opcional) Inicializar las demandas con algún valor de arranque for (int i = 0; i < demandaRecursos.Length; i++) { // Por ejemplo, el consumo inicial podría ser simplemente el porcentaje base * población inicial demandaRecursos[i] = porcentajeBaseMP[i] * poblacionActual; } } /// <summary> /// Llamar en cada ciclo para recalcular la población y la demanda. /// </summary> public void CalcularDemanda() { // ================================================== // 1) Calcular la nueva población (poblacionTotal = poblacionAnterior ± Δ2) // Δ2 = (eventos aleatorios) ± (temporada) ± Δ3 // ================================================== float eventoPop = Random.Range(minEventoPoblacion, maxEventoPoblacion); // "eventos aleatorios" para población float factorTemporadaPop = esInvierno ? factorInviernoPoblacion : factorVeranoPoblacion; // invierno/verano float delta3 = Random.Range(minDelta3, maxDelta3); // número extra aleatorio float delta2 = eventoPop + factorTemporadaPop + delta3; // Este es tu Δ2 poblacionActual += delta2; // Evitar población negativa if (poblacionActual < 0) poblacionActual = 0; // ================================================== // 2) Para cada MP, calcular Demanda = consumidores ± Δ1 // donde consumidores = %poblacionTotal // y Δ1 = (eventos aleatorios) ± (temporada) // ================================================== // Elegimos un factor de temporada para la DEMANDA float factorTemporadaDemanda = esInvierno ? factorInviernoDemanda : factorVeranoDemanda; for (int i = 0; i < demandaRecursos.Length; i++) { // Base: porcentaje de la población que demanda este MP float consumidores = porcentajeBaseMP[i] * poblacionActual; // "eventos aleatorios" específicos para la demanda de este MP float eventoDemandMP = Random.Range(minEventoDemanda, maxEventoDemanda); // Δ1 = eventoDemandMP + factorTemporadaDemanda float delta1 = eventoDemandMP + factorTemporadaDemanda; // Demanda final para esta MP float nuevaDemanda = consumidores + delta1; // Asegurar que no sea negativa if (nuevaDemanda < 0) nuevaDemanda = 0; demandaRecursos[i] = nuevaDemanda; } // Debug opcional Debug.Log(">>> DEMANDA recalculada. " + "\nPoblación = " + poblacionActual + "\nDemanda MP1 = " + demandaRecursos[0] + "\nDemanda MP2 = " + demandaRecursos[1]); } }
Población
Δ2
con la fórmula:
donde:
Δ2
a poblacionActual
, y se evita que baje de 0.Demanda por MP
porcentajeBaseMP[i] * poblacionActual
.
porcentajeBaseMP[0] = 0.12
, significa que un 12% de la población consume MP1.Δ1
= (evento aleatorio para la demanda) + (factor de temporada para la demanda).
Demanda = consumidores + Δ1
.Evitar negativos
Rangos y factores
minEventoPoblacion
, maxEventoPoblacion
, factorInviernoPoblacion
, factorVeranoPoblacion
, etc., son ajustables en el Inspector para que puedas afinar la magnitud de los cambios.porcentajeBaseMP
es un array donde cada posición define el porcentaje de población que consume una materia prima (MP1..MP9).Invocación
GameManager
suscrito a onCicloCompleto
), llamas a demandManager.CalcularDemanda()
.Este script ilustra una forma de implementar tu fórmula:
donde se incluyen factores estacionales, eventos aleatorios y un número adicional . Además, cada MP tiene un porcentaje distinto de la población que la consume, resultando en demandas iniciales diferentes para cada MP. Luego se añaden variaciones de temporada y eventos para que cada materia prima fluctúe de forma separada y un poco impredecible.
la poblacion crece de forma incercial con este script? por ejemplo, si en el ciclo 1 inicio con 100 de poblacion, en el ciclo 2 la poblacion será 100 + delta 2 (eventos, temporada), digamos queda en 112, y en el ciclo 3 la poblacion será 112 + delta 2, osea, toma el valor de la poblacion del ultimo ciclo
Sí, exactamente. Tal como está escrito el script:
csharp// ... float delta2 = eventoPop + factorTemporadaPop + delta3; poblacionActual += delta2; // ...
se va acumulando la nueva población sobre la anterior. En cada ciclo, el valor de poblacionActual
será:
población del ciclo anterior + (eventos + temporada + número aleatorio)
Por ejemplo:
De esta manera, cada ciclo se toma como punto de partida la población del ciclo anterior, lo cual produce ese crecimiento (o decrecimiento) inercial. Si quisieras que cada ciclo la población se recalculara partiendo de un valor fijo, tendrías que reasignar la población en lugar de sumarla (por ejemplo, poblacionActual = basePoblacion + delta2
), pero con la lógica actual se “arrastra” el valor desde el ciclo previo.
using UnityEngine;
public class ofertaMercado : MonoBehaviour
{
public recursos scriptRecursos;
textpublic float[] ofertaMP = new float[9]; // producción base de los NPCs public float[] prodBaseNPC1MP = new float[9] { 12, 3, 1, 0, 0, 0, 0, 0, 0 }; public float[] prodBaseNPC2MP = new float[9] { 6, 9, 2, 0, 0, 0, 0, 0, 0 }; public float[] prodBaseNPC3MP = new float[9] { 18, 6, 3, 0, 0, 0, 0, 0, 0 }; // variación en la produccón public float[] varProdNPC1MP = new float[9] { 12, 3, 1, 0, 0, 0, 0, 0, 0 }; public float[] varProdNPC2MP = new float[9] { 6, 9, 2, 0, 0, 0, 0, 0, 0 }; public float[] varProdNPC3MP = new float[9] { 18, 6, 3, 0, 0, 0, 0, 0, 0 }; // producción total de los NPCs public float[] produccionNPC1MP = new float[9]; public float[] produccionNPC2MP = new float[9]; public float[] produccionNPC3MP = new float[9]; public void CalcularOferta() { for (int i = 0; i < 9; i++) { float delta1 = Random.Range(-varProdNPC1MP[i], varProdNPC1MP[i]); produccionNPC1MP = prodBaseNPC1MP + delta1; if (produccionNPC1MP[i] < 0) produccionNPC1MP[i] = 0; float delta2 = Random.Range(-varProdNPC2MP[i], varProdNPC2MP[i]); produccionNPC2MP = prodBaseNPC2MP + delta2; if (produccionNPC2MP[i] < 0) produccionNPC2MP[i] = 0; float delta3 = Random.Range(-varProdNPC3MP[i], varProdNPC3MP[i]); produccionNPC3MP = prodBaseNPC3MP + delta3; if (produccionNPC3MP[i] < 0) produccionNPC3MP[i] = 0; } int[] prodJugadorMP = new int[] { scriptRecursos.mP1, scriptRecursos.mP2, scriptRecursos.mP3, scriptRecursos.mP4, scriptRecursos.mP5, scriptRecursos.mP6, scriptRecursos.mP7, scriptRecursos.mP8, scriptRecursos.mP9 }; for (int i = 0; i < 9; i++) { ofertaMP[i] = produccionNPC1MP[i] + produccionNPC2MP[i] + produccionNPC3MP[i] + prodJugadorMP[i]; } Debug.Log(">>>OFERTA RECALCULADA. " + "\nGrano = " + ofertaMP[0] + "\nHortalizas = " + ofertaMP[1] + "\nFruta = " + ofertaMP[2]); }
}
Assets\Scripts\inicio1\sistemaEconomico\mercado\ofertaMercado.cs(29,32): error CS0019: Operator '+' cannot be applied to operands of type 'float[]' and 'float'
Assets\Scripts\inicio1\sistemaEconomico\mercado\ofertaMercado.cs(33,32): error CS0019: Operator '+' cannot be applied to operands of type 'float[]' and 'float
Assets\Scripts\inicio1\sistemaEconomico\mercado\ofertaMercado.cs(37,32): error CS0019: Operator '+' cannot be applied to operands of type 'float[]' and 'float'
El problema ocurre porque en estas líneas estás intentando hacer:
csharpproduccionNPC1MP = prodBaseNPC1MP + delta1;
y C# interpreta que prodBaseNPC1MP
es un array (float[]
), mientras que delta1
es un float, y no puedes sumar directamente un array y un float.
Lo que quieres realmente es actualizar la posición i
del array produccionNPC1MP
con la suma de la posición i
de prodBaseNPC1MP
más el valor de delta1
.
En otras palabras, la corrección es:
csharpproduccionNPC1MP[i] = prodBaseNPC1MP[i] + delta1; produccionNPC2MP[i] = prodBaseNPC2MP[i] + delta2; produccionNPC3MP[i] = prodBaseNPC3MP[i] + delta3;
csharpusing UnityEngine; public class ofertaMercado : MonoBehaviour { public recursos scriptRecursos; public float[] ofertaMP = new float[9]; // producción base de los NPCs public float[] prodBaseNPC1MP = new float[9] { 12, 3, 1, 0, 0, 0, 0, 0, 0 }; public float[] prodBaseNPC2MP = new float[9] { 6, 9, 2, 0, 0, 0, 0, 0, 0 }; public float[] prodBaseNPC3MP = new float[9] { 18, 6, 3, 0, 0, 0, 0, 0, 0 }; // variación en la producción (máximos +/-) public float[] varProdNPC1MP = new float[9] { 12, 3, 1, 0, 0, 0, 0, 0, 0 }; public float[] varProdNPC2MP = new float[9] { 6, 9, 2, 0, 0, 0, 0, 0, 0 }; public float[] varProdNPC3MP = new float[9] { 18, 6, 3, 0, 0, 0, 0, 0, 0 }; // producción total de los NPCs (resultado en cada ciclo) public float[] produccionNPC1MP = new float[9]; public float[] produccionNPC2MP = new float[9]; public float[] produccionNPC3MP = new float[9]; public void CalcularOferta() { for (int i = 0; i < 9; i++) { float delta1 = Random.Range(-varProdNPC1MP[i], varProdNPC1MP[i]); // Asigna valor a produccionNPC1MP[i], no al array completo produccionNPC1MP[i] = prodBaseNPC1MP[i] + delta1; if (produccionNPC1MP[i] < 0) produccionNPC1MP[i] = 0; float delta2 = Random.Range(-varProdNPC2MP[i], varProdNPC2MP[i]); produccionNPC2MP[i] = prodBaseNPC2MP[i] + delta2; if (produccionNPC2MP[i] < 0) produccionNPC2MP[i] = 0; float delta3 = Random.Range(-varProdNPC3MP[i], varProdNPC3MP[i]); produccionNPC3MP[i] = prodBaseNPC3MP[i] + delta3; if (produccionNPC3MP[i] < 0) produccionNPC3MP[i] = 0; } // Conversión a int[] de las materias primas del jugador int[] prodJugadorMP = new int[] { scriptRecursos.mP1, scriptRecursos.mP2, scriptRecursos.mP3, scriptRecursos.mP4, scriptRecursos.mP5, scriptRecursos.mP6, scriptRecursos.mP7, scriptRecursos.mP8, scriptRecursos.mP9 }; // Sumamos las producciones totales de NPC1, NPC2, NPC3 y el jugador for (int i = 0; i < 9; i++) { ofertaMP[i] = produccionNPC1MP[i] + produccionNPC2MP[i] + produccionNPC3MP[i] + prodJugadorMP[i]; } Debug.Log(">>>OFERTA RECALCULADA. " + "\nGrano = " + ofertaMP[0] + "\nHortalizas = " + ofertaMP[1] + "\nFruta = " + ofertaMP[2]); } }
Con esto, se soluciona el error CS0019 ("Operator '+' cannot be applied to operands of type 'float[]' and 'float'"), puesto que ahora estamos sumando valores elemento a elemento en el array en lugar de intentar sumar un array completo con un valor flotante.