С ростом списка улучшений мне приходится реорганизовывать свой код, чтобы он был модульным и чище. Иногда мы можем реализовать функцию и не осознавать, что эта конкретная функция должна быть модульной.
Цель
Цель состоит в том, чтобы разбить на модули и реорганизовать функцию, которая управляет появлением бонусов.
Модульность
Для модульной системы включения нам нужна система идентификации, чтобы можно было идентифицировать каждое включение. Вы можете использовать либо переменную типа данных int, либо, в моем случае, перечисление. Перечисления предоставляют строку для идентификации объекта, но также присваивают значение за именем.
public enum PowerupType { None, // 0 TripleShot, // 1 Speed, // 2 Shield // 3 }
Мне нужно использовать перечисление в сценарии Powerup, чтобы мы могли назначить тип предмету коллекционирования. Таким образом, мы можем инициализировать переменную типа PowerupType
и объявить ее с типом PowerupType.None
по умолчанию.
[SerializeField] private PowerupType _powerupType = PowerupType.None;
Это позволит нам выбрать тип включения в инспекторе.
Теперь мы можем использовать оператор switch
для проверки отдельных функций бонусов.
private void OnTriggerEnter2D(Collider2D other) { if (other.CompareTag(“Player”)) { var player = other.transform.GetComponent<Player>(); if(player != null) { switch (_powerupType) { case PowerupType.TripleShot: player.TripleShotActive(); break; case PowerupType.Speed: player.SpeedBoostActive(); break; case PowerupType.Shield: player.ShieldActive(); break; default: _powerupType = PowerupType.None; break; } } Destroy(gameObject); } }
Когда игрок сталкивается с типом усиления, он проходит через переключатель, находит нужный тип и активирует его, вызывая функцию из сценария игрока.
Рефакторинг
Вот функция, которая нуждается в рефакторинге:
private IEnumerator SpawnPowerUpRoutine() { while (!_stopSpawning) { float randomX = Random.Range(-11, 11); Vector3 randonXposition = new Vector3(randomX, 8, 0); Instantiate(_tripleShotPrefab, randonXposition, Quaternion.identity); float randomTime = Random.Range(6, 20); yield return new WaitForSeconds(randomTime); } }
Как видите, жирным шрифтом выделено только одно усиление.
Мне нужно изменить _tripleShotPrefab
на массив GameObjects
.
Массив — это фиксированный список, размер которого не может измениться во время работы игры. Он должен иметь длину при определении и не может быть изменен. Он является частью семейства коллекций C#, наряду со списком, словарем, очередью и стеком.
Я изменил переменную _tripleShotPrefab
на это:
[SerializeField] private GameObject[] _powerupPrefabs = null;
Теперь он принимает набор GameObject
, и мы, программисты или дизайнеры, можем настроить количество игровых объектов, которые он может хранить в инспекторе.
Теперь я должен изменить то, как мы создаем бонусы.
В функции SpawnPowerUpRoutine() мне нужно изменить переменную _tripleShotPrefab
на _powerupPrefabs[]
. Компилятор выдаст нам ошибку.
_powerupPrefabs[]
нужно значение в нижнем индексе (скобки). Помните, я хочу, чтобы наша система повышения мощности была модульной. Итак, давайте создадим локальный тип данных int, который может рандомизировать длину нашего массива _powerupPrefabs
.
int randomPowerup = Random.Range(0, _powerupPrefabs.Length);
Переменная randomPowerup
будет содержать случайное число из числа включений, которые мы храним в массиве _powerupPrefabs
. Это позволит случайным образом создавать все бонусы.
private IEnumerator SpawnPowerUpRoutine() { while (!_stopSpawning) { float randomX = Random.Range(-11, 11); Vector3 randonXposition = new Vector3(randomX, 8, 0); int randomPowerup = Random.Range(0, _powerupPrefabs.Length); Instantiate(_powerupPrefabs[], randonXposition, Quaternion.identity); float randomTime = Random.Range(6, 20); yield return new WaitForSeconds(randomTime); } }
Мне нужно передать randomPowerup
в нижний индекс _powerupPrefabs
внутри функции Instantiate()
.
private IEnumerator SpawnPowerUpRoutine() { while (!_stopSpawning) { float randomX = Random.Range(-11, 11); Vector3 randonXposition = new Vector3(randomX, 8, 0); int randomPowerup = Random.Range(0, _powerupPrefabs.Length); Instantiate(_powerupPrefabs[randomPowerup], randonXposition, Quaternion.identity); float randomTime = Random.Range(6, 20); yield return new WaitForSeconds(randomTime); } }
Закончив рефакторинг, я могу вернуться в Unity, щелкнуть игровой объект Spawn Manager, к которому прикреплен скрипт SpawnManager, и назначить наши префабы массиву _powerupPrefabs
в инспекторе.
Перетащите бонусы в массив, и готово!
Теперь у нас есть модульная система усиления!
Вывод
Используя массив, я разбиваю на модули систему, которая могла бы быть запутанной с операторами if и else. Я поражен тем, насколько эффективным и чистым стало это небольшое изменение.
Следующим усилением, которое нужно реализовать, будут щиты!
Это все на сегодня. Спасибо за чтение!