Генерация предметов
Есть инвентарь сундука, в который нужно сгенерировать несколько предметов по особым правилам. Предметы типа Weapon и Ability генерируются в зависимости от уровня, каждый уровень со своей вероятностью и тут первая проблема, на данный момент все генерируется по такой схеме, есть массив с уровнями, где каждому уровню присвоено число чем больше число, тем выше шанс генерации. Я просто складываю все числа в массиве и генерирую рандомное от 0 до суммы, в какой промежуток выпало тот уровень и выпадает. Например, у нас есть 3 уровня: 1 - 100, 2 - 50, 3 - 30, сумма выходит 180, мы генерируем число от 0 до 180 если выпадает меньше 100, то первый уровень если выпадает больше 100, но меньше 150 то второй и т.д. Вот код:
protected int GetArraySum(int[] array, int id1, int id2)
{
var sum = 0;
for (int i = id1; i < id2+1; i++)
{
sum+=array[i];
}
return sum;
}
protected int RandomRules(int[] chanceArray) // Возвращает уровень предмета, chanceArray это массив уровней вроде: 1 - 100, 2 - 50, 3 - 30
{
var rand = Random.Range(0, chanceArray.Sum());
if (0 <= rand && rand < GetArraySum(chanceArray, 0, 0))
{
return 0;
}
for (int i = 1; i < chanceArray.Length; i++)
{
if (GetArraySum(chanceArray, 0, (i-1)) <= rand && rand < GetArraySum(chanceArray, 0, i))
{
return i;
}
}
return 0;
}
Ниже генерация предметов, где нужно обратить внимание на Weapons and abilities, там уже видно проблемы, не придумал ничего лучше, чем просто бесконечно генерировать в цикле пока не выпадет предмет нужного уровня. В конце проверка на то есть ли уже этот предмет у игрока, предмет можно поднять только 1 раз и навсегда, а значит рано или поздно предметы определенного уровня закончатся и начнется бесконечный цикл, как это решить кроме как городить кучу if и вести подсчет предметов по уровням, я не придумал поэтому тут нет решения. Код:
[Header("Prefabs")]
[SerializeField] private GameObject itemPrefab;
[Header("Chance LVL Settings")]
[SerializeField] public int[] LvlProgression;
public Item Make(int _itemID = -1, string _rulesType = "Corpse")
{
InfoItem infoItem;
if (_itemID == -1) infoItem = MakeInfo(_rulesType);
else infoItem = Game.Data.ItemList[_itemID];
return spawn(infoItem);
}
public InfoItem MakeInfo(string _rulesType)
{
InfoItem item;
var rand = Random.Range(0, 100);
switch (_rulesType)
{
case "Corpse":
{
if (rand < 60) // MONEY
{
item = Game.Data.ItemList[0];
item.cost = Random.Range(1, 16);
}
else if (rand < 90) // HALF HEAL
{
if (Random.Range(0, 3) <= 2)
{
item = Game.Data.ItemList[2];
}
else item = Game.Data.ItemList[4];
}
else if (rand < 95) // FULL HEAL
{
if (Random.Range(0, 3) <= 2)
{
item = Game.Data.ItemList[1];
}
else item = Game.Data.ItemList[3];
}
else// Weapons and abilities
{
var itemLvl = RandomRules(LvlProgression);
item = Game.Data.ItemList[Random.Range(5, 10)];
bool find = false;
while (!find)
{
item = Game.Data.ItemList[Random.Range(5, 10)];
if (item.lvl == itemLvl)
{
find = true;
}
if (Game.singletone.Player.InventoryEquipment.Count.ContainsKey(item.id)) find = false; // проверка на то есть ли предмет у игрока если есть то генеририруем еще раз
}
}
return item;
}
default:
{
item = Game.Data.ItemList[0];
return item;
}
}
}
Ну и самое главное предмет можно поднять только один раз, после чего он появятся у игрока навсегда, а значит нельзя генерировать одинаковые предметы типа Weapon и Ability в одном сундуке написал вот так вот, по мимо того что это выглядит ужасно так предметы определенного уровня могут и закончится а миллион циклов в цикле это просто гг, учитывая что при каждой генерации происходит все то что я описал выше.
public void GenerateItems()
{
Game.UIManager.UILoot.UpdateInventory("Clear", UiName: Info.title);
var count = Random.Range(1, 4); // генерируем количесетво предметов в сундуке
for (int slot = 0; slot < count; slot++) // slot - слот который будем заполнять
{
Item item = Game.FactoryItem.Make(); // slot - слот который будем заполнять
if (item.Info.type == "Weapon" || item.Info.type == "Ability") // если предмет оружие или способность
{
bool find = false;
if (slot == 0) find = true; //Если первый предмет в сундуке просто генерируем его
while (!find) //Проверяем все предметы на совпадение если совпало то просто гененируем еще раз
{
for (int i2 = 0; i2 < slot; i2++)
{
if (Inventory.Items[i2].Info.id == item.Info.id)
{
find = false; break;
}
else
{
find = true;
}
}
item = Game.FactoryItem.Make();
}
}
item.gameObject.transform.SetParent(gameObject.transform);
item.Slot = slot;
Inventory.Add(item, slot);
Game.UIManager.UILoot.UpdateInventory("Add", slot, item);
}
}
Если кто-то сталкивался с подобным или есть предложения по улучшению и исправлению проблем буду раз услышать. По итогу 3 проблемы, что делать с тем, что куча циклов в цикле, что делать с тем, что предметы определенного уровня закончатся, и есть ли способ лучше генерировать не одинаковые предметы типа Weapon и Ability в сундуке.