Для начала, нужна добавить компонент, который будет отвечать за состояние монеток. C его помощью, мы сможем отключать те монетки, которые были собраны:
using System.Text;
internal sealed class EnumerableContainer
{
[SerializeField] private Coin[] Coins;
public void SetDeactivateCoin(int id)
{
for (int iterator = 0; iterator < id; iterator++)
{
if (Coins[iterator].Id == id)
{
Coins[iterator].State = false;
break;
}
}
}
public string ToJson()
{
StringBuilder stringBuilder = new StringBuilder(capacity: 256);
foreach (Coin coin in Coins)
stringBuilder.AppendFormat("{0}:", JsonUtility.ToJson(coin));
return stringBuilder.ToString();
}
public void FromJson(string data)
{
string[] buffer = data.Split(':', StringSplitOptions.RemoveEmptyEntries);
int iterator = 0;
foreach (string coinData in buffer)
{
Coin coin = JsonUtility.FromJson(coinData);
Coins[iterator].State = coin.State;
if (!Coins[iterator].State)
Coins[iterator].gameObject.SetActive(false);
iterator++;
}
}
}
Следующий компонент будет отвечать за сбор самих монет и изменять их состояние:
internal sealed class CollectCoinsCounter : Monobehaviour
{
public event Action<int> OnChangeValue;
public int GetCountCoin => _coins;
private int _coins;
private void OnTriggerEnter(Collider collider)
{
if (collider.TryGetComponent<Coin>(out Coin coin))
{
_coins += coin.Cost;
coin.State = false;
coint.gameObject.SetActive(false);
UpdateText(_coins);
}
}
public void UpdateText(int value)
{
OnChangeValue.Invoke(value);
}
public void SetCountCoin(int count)
{
_coins = count;
}
}
Компонент, который будет отвечать за обновление пользовательского интерфейса:
[RequireComponent(typeof(CollectCoinsCounter))]
internal sealed class UpdateUI : Monobehaviour
{
[SerializeField] private TMP_Text _text;
private CollectCoinsCounter _collect;
private void Awake()
{
_collect = GetComponent<CollectCoinsCounter>();
}
private void OnEnable() => _collect.OnChangeValue += OnChangeValue;
private void OnDisable() => _collect.OnChangeValue -= OnChangeValue;
private void OnChangeValue(int obj)
{
_text.text = string.Format("Coins: {0}", obj);
}
}
Один из главных компонентов - сама модель монетки. Такой компонент обязан быть привязан к самим монеткам:
internal sealed class Coin : Monobehaviour
{
public int Id;
public int Cost;
public bool State = true;
}
И компонент сохранение/загрузки состояние монет:
[RequireComponent(typeof(EnumerableContainer))]
[RequireComponent(typeof(CollectCoinsCounter))]
internal sealed class SavedCoin : Monobehaviour
{
private readonly string _prefName = "CoinsCount";
private readonly string _prefNameState = "CoinsState";
private EnumerableContainer _enumerableContainer;
private CollectCoinsCounter _collect;
private void Awake()
{
_enumerableContainer = GetComponent<EnumerableContainer>();
_collect = GetComponent<CollectCoinsCounter>();
}
private void Start()
{
if (PlayerPrefs.HasKey(_prefName))
{
int count = PlayerPrefs.GetInt(_prefName);
_collect.UpdateText(count);
_collect.SetCountCoin(count);
}
if (PlayerPrefs.HasKey(_prefNameState))
_enumerableContainer.FromJson(PlayerPrefs.GetString(_prefNameState));
}
private void OnApplicationQuit()
{
PlayerPrefs.SetInt(_prefName, _collect.GetCountCoin);
PlayerPrefs.SetString(_prefNameState, _enumerableContainer.ToJson());
}
}