Не удается увеличить максимальное число резидентов
первый раз делаю игру на unity и C#, на данный момент, проблема в том, что я не знаю, как с использованием триггера увеличить максимальное число резидентов. \
Как это должно работать: Есть дом, который увеличивает максимальное число резидентов на 6, к нему я пристраиваю вышку, которая должна увеличить то же число, но уже на 3.
Для этого всего я использую Box Collider, в котором выставлены галочки на Is trigger, Rigibody я так же поставил. Когда я строю вышку, то число не возрастает,
вот код:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class House : MonoBehaviour
{
public int resident;
public int maxResident;
public int residentAdd;
float residentTime;
public int energy;
public int energyUse;
float energyTime;
public int residentDied;
float DiedTime;
public int tax;
public int taxAdd;
float taxTime;
`GameObject resources;
void Start()
{
resources = GameObject.FindGameObjectWithTag("resourcesController");
resources.GetComponent<ResourcesController>().maxResident += maxResident;
resources.GetComponent<ResourcesController>().building += 1;
}
void Update()
{
if (resident < 0)
{
resident = 0;
}
ResidentAdd();
Energy();
Tax();
Died();
}
void ResidentAdd()
{
residentTime += 1 * Time.deltaTime;
if (residentTime >= residentAdd)
{
if (resources.GetComponent<ResourcesController>().resident < resources.GetComponent<ResourcesController>().maxResident)
{
if (resident < maxResident)
{
resident += 1;
resources.GetComponent<ResourcesController>().resident += 1;
}
}
residentTime = 0;
}
}
void Energy()
{
int allEnergy;
energyTime += 1 * Time.deltaTime;
if(energyTime >= energyUse)
{
allEnergy = resident * energy;
if(allEnergy <= resources.GetComponent<ResourcesController>().energy)
{
resources.GetComponent<ResourcesController>().energy -= allEnergy;
} else
{
while(allEnergy > resources.GetComponent<ResourcesController>().energy)
{
resident -= 1;
resources.GetComponent<ResourcesController>().resident -= 1;
allEnergy -= 1;
}
}
allEnergy = 0;
energyTime = 0;
}
}
void Tax()
{
int allTax;
taxTime += 1 * Time.deltaTime;
if (taxTime >= taxAdd)
{
allTax = resident * tax;
resources.GetComponent<ResourcesController>().gold += allTax;
allTax = 0;
taxTime = 0;
}
}
void Died()
{
DiedTime += 1 * Time.deltaTime;
if (DiedTime >= residentDied)
{
resident -= 1;
resources.GetComponent<ResourcesController>().resident -= 1;
DiedTime = 0;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Tower")
{
maxResident += 3;
}
}
}
Ответы (1 шт):
// если не используются, их не должно быть
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class House : MonoBehaviour
{
// публичных полей не должно быть
// тут 3 разные отвественности resident, energy и tax которые должны быть выделины в 3 разных класс
public int resident;
public int maxResident;
public int residentAdd;
float residentTime;
public int energy;
public int energyUse;
float energyTime;
public int residentDied;
float DiedTime;
public int tax;
public int taxAdd;
float taxTime;
// почему GameObject? сразу ResourcesController нельзя?
GameObject resources;
void Start ()
{
// FindGameObject вообще пользоваться, категорически неправильно
// FindGameObjectWithTag тем более, строковые литералы пораждают ошибки
// Классы более низкого уровня не должны знать о существовании класса более высокого, а ResourcesController выше House
resources = GameObject.FindGameObjectWithTag("resourcesController");
// GetComponent это операция затрачивающая ресурсы
// ResourcesController дублирует значения, этого не болжно быть, как и самого ResourcesController в House
resources.GetComponent<ResourcesController>().maxResident += maxResident;
resources.GetComponent<ResourcesController>().building += 1;
}
void Update ()
{
// условие явно лечит неподконтрольное изменение значения, костыли
if (resident < 0)
{
resident = 0;
}
// хорошо что ты поделил 4 процесса на 4 метода, но названия не отображает что в них
ResidentAdd(); // UpdateGeneration (в раммках класса Residents)
Energy();
Tax();
Died(); // UpdateDisappearance (в раммках класса Residents)
}
void ResidentAdd ()
{
// 1*Time.deltaTime = Time.deltaTime
residentTime += 1 * Time.deltaTime;
if (residentTime >= residentAdd)
{
// если ResourcesController дублирует суммарное количество значений в домах то эта проверка не имеет смысла
if (resources.GetComponent<ResourcesController>().resident < resources.GetComponent<ResourcesController>().maxResident)
{
if (resident < maxResident)
{
resident += 1;
resources.GetComponent<ResourcesController>().resident += 1;
}
}
// а куда девается остаток?
residentTime = 0;
}
}
void Energy ()
{
int allEnergy;
energyTime += 1 * Time.deltaTime;
if (energyTime >= energyUse)
{
// смысл объявлять allEnergy ранее?
// все энергия = житель * энергия... бросай наркотики
// видимо речь про потребление энергии, тогда так и нужно называть energyСonsumption
// или скорее назвать energyRequired, а сам метод UpdateСonsumption (в раммках класса Energy), тогда все начнет иметь смысл
allEnergy = resident * energy;
if (allEnergy <= resources.GetComponent<ResourcesController>().energy)
{
resources.GetComponent<ResourcesController>().energy -= allEnergy;
}
else
{
while (allEnergy > resources.GetComponent<ResourcesController>().energy)
{
resident -= 1;
resources.GetComponent<ResourcesController>().resident -= 1;
allEnergy -= 1;
}
}
// не там обьявил и теперь нужны костыли
allEnergy = 0;
energyTime = 0;
}
}
void Tax ()
{
int allTax;
taxTime += 1 * Time.deltaTime;
if (taxTime >= taxAdd)
{
// сново здарово
// all переводится как "все", но речь все таки штуках, а о суммарном/общем налоге totalTax
allTax = resident * tax;
// весь метод именно ради этого и посвещен он вовсе не налогу, то-есть вычитании денег, а получении дохода, то-есть UpdateIncome
resources.GetComponent<ResourcesController>().gold += allTax;
// сново здарово
allTax = 0;
taxTime = 0;
}
}
void Died ()
{
// сново здарово
DiedTime += 1 * Time.deltaTime;
if (DiedTime >= residentDied)
{
resident -= 1;
resources.GetComponent<ResourcesController>().resident -= 1;
DiedTime = 0;
}
}
// ни разу не писал private и тут на... вообще-то везде должны быть включая поля, ну или нигде, чисто ради консистенции, чтоб не шеш беш
private void OnTriggerEnter (Collider other)
{
// опять строковый литерал, работа с ними не безопасна, нужно проверять на компонент или интерфейс
// если House или Tower могут столкнуться, значит кто-то из них или оба двигаются... бросай наркотики
if (other.tag == "Tower")
{
// это что? Tower трахнул House толи в дымоход толи в парадную и... бросай тяжелые наркотики
maxResident += 3;
}
}
}
ResourcesController какой-то монструозный класс, там буквально все, включая такой ресурс как maxResident ?.
Такого класса вообще не должно быть. Инфа по домам отдельно, валюта отдельно
public class HouseManager
{
private List<House> _houses;
// добавляет некий HouseSpanwer
public void AddHouse (House house)
{
_houses.Add(house);
}
public int GetResidentsCount ()
{
int count = 0;
foreach (House house in _houses)
count += house.Residents.CurrentCount;
return count;
}
public int GetResidentsCapacity ()
...
}
Валюта к сцене не привязана, для нее лучше использовать singleton
[Serializable]
public struct CurrencyAmount
{
public int Gold;
public int Diamonds;
}
public enum CurrencyType { Gold, Diamonds }
public class Currency
{
private const string Key = "Currency";
private static Currency _instance;
public Action<CurrencyType, int> Changed;
private CurrencyAmount _amount;
private Currency ()
{
Load();
}
public static Currency Instance
{
get
{
if (_instance == null)
_instance = new Currency();
return _instance;
}
}
public int Gold
{
get => GetAmount(CurrencyType.Gold);
set => SetAmount(CurrencyType.Gold, value);
}
public int Diamonds
{
get => GetAmount(CurrencyType.Diamonds);
set => SetAmount(CurrencyType.Diamonds, value);
}
public int GetAmount (CurrencyType currency)
{
switch (currency)
{
case CurrencyType.Gold: return _amount.Gold;
case CurrencyType.Diamonds: return _amount.Diamonds;
default: return 0;
}
}
public void SetAmount (CurrencyType currency, int amount)
{
switch (currency)
{
case CurrencyType.Gold: _amount.Gold = amount; break;
case CurrencyType.Diamonds: _amount.Diamonds = amount; break;
}
Changed?.Invoke(currency, amount);
Save();
}
private void Load ()
{
if (PlayerPrefs.HasKey(Key))
{
string json = PlayerPrefs.GetString(Key);
_amount = JsonUtility.FromJson<CurrencyAmount>(json);
}
}
private void Save ()
{
string json = JsonUtility.ToJson(_amount);
PlayerPrefs.SetString(Key, json);
PlayerPrefs.Save();
}
}