Всем привет!
Есть следующий вопрос. Вопрос касается не реализации, а в выборе логике.
Я перепробовал много вариантов, и перечитал разных статей, и никак не могу определиться с логикой хранение и потом извлечение ресурсов.
Задача:
Хранить и использовать разные спрайты, в разных местах. (Кастомизация персонажа, аукцион, предметы в почте, покупка в магазине и так далее). Информация, что подгружать будет приходить от сервера
Описание:
Игра 2д
У меня спрайты:
-Одежды в виде нарезки (то есть элемент поделен на 12 кусков)
-Оружия
-Иконок для магазина и прочих мест
Возьмем пример с кастомизации персонажа при его создании, логика следующая:
при старте игры идет запрос к серверу, откуда в файл записывается информация о классах всех и какая у него экипировка. Далее префаб игрока надевает это на себя в зависимости от выбора игрока.
Сам персонаж нарезан на куски (типо тело, голова, оружие и тому подобное), и на каждой части есть spriteRender куда я креплю спрайт
Примерно тот же алгоритм для иконок, которые доступны для Кастомизации (глаза, волосы и прочее), тут я имею ввиду кнопки для выбора смены спрайта. То есть нужно грузить иконку для отображения кнопки и спрайт потом для изменения персонажа.
Тут можно сделать статику, на этапе создания персонажа. Но дальше статика уже не очень подходит, так как Кастомизацию планирую делать не совсем открытую так скажем, то есть спрайты будут также динамически и какой-нибудь пагинацией наверное.
Что пробовал:
папка resource - почитал и просто не понравилось
assetsBandle - интересно, вроде работает как надо. Но из-за того, что спрайты нарезаны одежды, то мне на каждую экипировку надо делать свой бандл, то есть не разделить по категориям, а прям на каждый спрайт. Так как если запрашивать у него один файл, то он отдает только первый. Если все, то вообще все, а названия там у всех одинаковые будут (типо рука, рука1, рука2) и имя закэшировано. Из-за этого не удобно для меня лично стало. Но тут не спорю, возможно, я туповат и не понял, как правильно с ним работать, но вроде всё по доке делал
Что-то ещё пробовал и забыл.
Сейчас реализовано, что в начале игры у меня загружается "вечный" префаб "database" с прикрепленным к нему scriptableObjects где есть вся инфа по спрайтам. Сделано в следующем формате:
public class ItemCollection: ScriptableObject
{
[SerializeField] private Item[] _item;
public Item[] Item => _item;
public Item[] GetItemCollection()
{
return _item;
}
}
public class Item
{
public int id;
public string name;
public Types type;
public Sprite[] sprites;
public Sprite icon;
}
а к "базе" так скажем обращаюсь следующим образом:
public class Database: MonoBehaviour
{
[SerializeField] private ItemCollection HeavyArmor;
[SerializeField] private ItemCollection LightArmor;
[SerializeField] private ItemCollection Swords;
[SerializeField] private ItemCollection Stuffs;
private Dictionary<string, Item> _lightArmor = new Dictionary<string, Item>();
private Dictionary<string, Item> _heavyArmor = new Dictionary<string, Item>();
private Dictionary<string, Item> _swords = new Dictionary<string, Item>();
private Dictionary<string, Item> _stuffs = new Dictionary<string, Item>();
private static Database instance;
public static Database Instance
{
get
{
if (instance != null) return instance;
instance = FindObjectOfType<Database>();
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
return;
}
var heavyArmorCollection = HeavyArmor.GetItemCollection();
var lengthHeavyArmor = heavyArmorCollection.Length;
for (var i = 0; i < lengthHeavyArmor; i++)
{
_heavyArmor.Add(heavyArmorCollection[i].name, heavyArmorCollection[i]);
}
var lightArmorCollection = LightArmor.GetItemCollection();
var lengthLightArmor = lightArmorCollection.Length;
for (var i = 0; i < lengthLightArmor; i++)
{
_lightArmor.Add(lightArmorCollection[i].name, lightArmorCollection[i]);
}
var swordsCollection = Swords.GetItemCollection();
var lengthSword = swordsCollection.Length;
for (var i = 0; i < lengthSword; i++)
{
_swords.Add(swordsCollection[i].name, swordsCollection[i]);
}
var stuffsCollection = Stuffs.GetItemCollection();
var lengthStuff = stuffsCollection.Length;
for (var i = 0; i < lengthStuff; i++)
{
_stuffs.Add(stuffsCollection[i].name, stuffsCollection[i]);
}
}
public Item GetLightArmorByName(string key)
{
return _lightArmor.GetValueOrDefault(key, null);
}
public Item GetHeavyArmorByName(string key)
{
return _heavyArmor.GetValueOrDefault(key, null);
}
public Item GetSwordByName(string key)
{
return _swords.GetValueOrDefault(key, null);
}
public Item GetStuffByName(string key)
{
return _stuffs.GetValueOrDefault(key, null);
}
public Dictionary<string, Sprite> PrepareSpriteEquipSet(Sprite[] sprites)
{
if (sprites.Length != 12)
{
throw new Exception("Invalid count Item");
}
return new Dictionary<string, Sprite>
{
{ Config.APP_EQUIP_PART_SET_ARM_L, sprites[0] },
{ Config.APP_EQUIP_PART_SET_ARM_R, sprites[1] },
{ Config.APP_EQUIP_PART_SET_WRIST sprites[2] },
{ Config.APP_EQUIP_PART_SET_SHOULDER_L, sprites[3] },
{ Config.APP_EQUIP_PART_SET_SHOULDER_R, sprites[4] },
{ Config.APP_EQUIP_PART_SET_HAND_L, sprites[5] },
{ Config.APP_EQUIP_PART_SET_HAND_R, sprites[6] },
{ Config.APP_EQUIP_PART_SET_LEGS, sprites[7] },
{ Config.APP_EQUIP_PART_SET_PELVIS, sprites[8] },
{ Config.APP_EQUIP_PART_SET_SHIN, sprites[9] },
{ Config.APP_EQUIP_PART_SET_SLEEVE, sprites[10] },
{ Config.APP_EQUIP_PART_SET_TORSO, sprites[11] }
};
}
}
P.S. код набросок, для моих тестов и чтоб всем понятно было)
в целом работает как надо, пока даже не ломается. Но я очень не уверен, что с ростом ресурсов эта ситуация останется на таком же уровне.
Что требуется:
помочь выбрать логику для моей задачи, потому что мне кажется, что я где-то рядом брожу и не вижу очевидного решения!)