Я действительно борюсь с созданием системы разблокировки оружия/предметов через внутриигровой магазин. Игрок должен иметь возможность выбирать оружие только по индексам, которые были разблокированы или куплены.
Я потратил два дня на лучший способ добиться этого, и я до сих пор не нашел решения.
На данный момент это то, что у меня есть:
У меня есть скрипт WeaponUnlock
, который обрабатывает dictionary
оружия, и еще один скрипт WeaponSwitcher
, который обращается к значениям из этого скрипта, чтобы проверить, разблокировано оно или нет.
public class WeaponUnlockSystem : MonoBehaviour
{
private Dictionary<string, bool> weaponUnlockState;
void Start()
{
// Seeding with some data for example purposes
weaponUnlockState = new Dictionary<string, bool>();
weaponUnlockState.Add("Shotgun", true);
weaponUnlockState.Add("Rifle", true);
weaponUnlockState.Add("FireballGun", false);
weaponUnlockState.Add("LaserGun", false);
weaponUnlockState.Add("FlamethrowerGun", false);
weaponUnlockState.Add("SuperGun", false);
}
public bool IsWeaponUnlocked(string weapon_)
{
if (weaponUnlockState.ContainsKey(weapon_))
return weaponUnlockState[weapon_]; // this will return either true or false if the weapon is unlocked or not
else
return false;
}
public void UnlockWeapon(string weapon_) //this will be called by the button..
{
if (weaponUnlockState.ContainsKey(weapon_))
weaponUnlockState[weapon_] = true;
}
}
WeaponSwitcher
получает название оружия от вложенных дочерних элементов каждый раз, когда нажимается кнопка nextWeapon
:
weaponName = this.gameObject.transform.GetChild(weaponIdx).name.ToString(); //get the name of the child at current index
if (weaponUnlock.IsWeaponUnlocked(weaponName)) //ask weaponUnlockSystem if this name weapon is unlocked or not, only enable the transform if true is returned
selectedWeapon = weaponIdx;
Это...... работает..... но я знаю, что это непрактично. Поскольку скрипт находится на игровом объекте, и каждый раз, когда он вызывается, вызывается Start()
, который сбрасывает все разблокированные значения. Также мне придется сделать его постоянным через DontDestroyOnLOad()
через сцены?
Я могу использовать PlayerPrefs
и установить значение для каждого оружия, но это тоже не идеально, а также, чтобы избежать его сброса каждый раз, когда кто-то открывает мою игру, мне пришлось бы выполнять проверки PlayerPrefs.HasKey()
для каждого оружия. Тоже не практично.
Должен быть лучший способ сделать это. Забавно, что я не могу найти много помощи в Интернете для этого и не знаю, как все обходят это.
Спасибо
Поскольку скрипт находится на игровом объекте, и каждый раз, когда он вызывается, вызывается Start()
, который сбрасывает все разблокированные значения. Также мне придется сделать его постоянным через DontDestroyOnLoad()
через сцены?
Просто создайте класс, который не является моноповедением, со «стандартными» логическими переменными и используйте ссылку на этот класс в чем-то вроде GameManager?
Возможный дубликат Лучший способ сохранить данные в игре Unity
Недавно у меня был проект Unity, где нам нужно было хранить и обрабатывать некоторые простые данные между сценами. Мы только что создали статический класс, который не расширяет моноповедение. Кроме того, если вы ищете эффективность, почему бы просто не сохранить набор разблокированного оружия?
В общем, почему бы не попробовать что-то вроде этого:
public static class WeaponUnlockSystem
{
private static string[] unlockedWeapons = InitialWeapons();
private static string[] InitialWeapons(){
string w = new string[]{
"Shotgun",
"Rifle",
}
}
public static bool IsWeaponUnlocked(string name)
{
int i = 0;
bool found = false;
while(i < unlockedWeapons.Length && !found){
if (string.Equals(unlockedWeapons[i],name)){
found = true;
}
i++;
}
return found;
}
public static void UnlockWeapon(string name)
{
string[] weapons = new string[unlockedWeapons.Length+1];
int i = 0;
bool found = false;
while(i < unlockedWeapons.Length && !found){
if (string.Equals(unlockedWeapons[i],name)){
found = true;
} else {
weapons[i] = unlockedWeapons[i];
}
}
if (!found){
weapons[unlockedWeapons.Length] = name;
unlockedWeapons = weapons;
}
}
Я не запускаю свою С# IDE, поэтому прошу прощения, если есть какие-либо синтаксические ошибки. Должен быть эффективным, простым и, поскольку он статичен, вам не нужно помещать его в пустой GameObject, чтобы он работал.
Вы создаете класс, который не является GameObject, а является обычным классом. Там вы можете инициализировать словарь и иметь методы для разблокировки или проверки того, разблокировано ли оружие.
Поскольку я не знаю, как выглядит ваша архитектура остального кода, я продолжу и предположу, что у вас есть какая-то модель постоянного проигрывателя.
Вы можете просто добавить WeaponUnlockSystem в свой GameObject игрока и оттуда управлять разблокировкой. Для меня это имело бы наибольший смысл, так как игрок, вероятно, тот, кто разблокирует оружие, поэтому к нему должна быть подключена Система Разблокировки Оружия.
Вот действительно простой пример кода:
public class WeaponUnlockSystem {
private Dictionary<string, bool> weaponUnlockState;
public WeaponUnlockSystem()
{
weaponUnlockState = new Dictionary<string, bool>();
weaponUnlockState.Add("Shotgun", true);
weaponUnlockState.Add("Rifle", true);
weaponUnlockState.Add("FireballGun", false);
weaponUnlockState.Add("LaserGun", false);
weaponUnlockState.Add("FlamethrowerGun", false);
weaponUnlockState.Add("SuperGun", false);
}
public bool IsWeaponUnlocked(string weapon)
{
if (weaponUnlockState.ContainsKey(weapon))
return weaponUnlockState[weapon];
else
return false;
}
public void UnlockWeapon(string weapon)
{
if (weaponUnlockState.ContainsKey(weapon))
weaponUnlockState[weapon] = true;
}
}
public class Player : MonoBehaviour {
private WeaponUnlockSystem weaponUnlockSystem;
void Start()
{
weaponUnlockSystem = new WeaponUnlockSystem();
...
}
public void NextWeapon(string weapon)
{
...
}
}
Я бы также посоветовал не использовать здесь статический класс для удобства. Статический следует использовать только в том случае, если вы не хотите изменять состояние объекта или вам не нужно создавать экземпляр объекта.
Каким образом вы считаете это непрактичным? Конечно, есть и другие решения, но нам нужен контекст того, чем вы недовольны.