Знакомство
Доброго времени суток, дорогие читатели, меня зовут Илья и я начинающий инди разработчик. Я впервые пишу статью и тем более впервые на тему разработки игр. В ней я хочу поделиться своим опытом создания простенького, но душевного раннера наподобие Динозаврика из Хрома. А называется он:

Сцена меню и визуал
Для разработки проекта я выбрал движок Unity, тк немного был с ним знаком. Я создал однотонный теплый фон, расставил окружающие объекты, это были кактусы, камешки, наш главный герой шериф Генри и конечно же бандит. Добавил облака которые появляются в случайный момент времени и оживил их при помощи простого скрипта.
[SerializeField] private float _speed = 1f; private void Update() { transform.Translate(_speed * Time.deltaTime * -1, 0, 0); }
Теперь они постоянно двигаются справа налево.
На сцене добавил кнопки меню и табличку с рекордом. В итоге первая сцена стала выглядеть вот так:

Механика игры
Наконец приступим к созданию самой игры. Я решил,что наш главный герой, шериф, будет находиться на месте, а все объекты будут двигаться ему навстречу.
За пределами видимости камеры я создал спавнеры объектов, а с другой стороны "корзину" для них, при попадании в триггер "мусорки" - объекты удаляются.

Теперь напишем код, который будет контролировать частоту создания объектов:
[SerializeField] private GameObject[] _templates; [SerializeField] private float _minDelay; [SerializeField] private float _maxDelay; [SerializeField] private float _devationPositionY = 0; [SerializeField] private float _spawnTime; private bool _isGameOver; private void Start() { _isGameOver = false; StartCoroutine(Spawn()); } private IEnumerator Spawn() { float minPositionY = transform.position.y - _devationPositionY; float maxPositionY = transform.position.y + _devationPositionY; while (_isGameOver == false) { float positionY = Random.Range(minPositionY, maxPositionY); _spawnTime = Random.Range(_minDelay, _maxDelay); var waitForSeconds = new WaitForSeconds(_spawnTime); GameObject gameObject = Instantiate(_templates[Random.Range(0, _templates.Length)], new Vector3(transform.position.x, positionY, transform.position.z), Quaternion.identity); yield return waitForSeconds; } }
И после создания заставим их двигаться навстречу главному герою, так будет создаваться впечатление, что игрок бежит сам. Осталось добавить анимацию бега и все готово:

Чтобы игра приобрела тот самый смысл раннера, создадим спавнер, из которого будут появляться бомбы, а нам в свою очередь, нужно будет перепрыгивать через них. И вот мы дошли до управления персонажем. Я уже добавил небольшую подсказку на экран, как управлять игроком, осталось реализовать.
[SerializeField] private float _jumpForce = 500; private Rigidbody2D _rigidbody2D; private bool _isGround; public event Action AnimationJumpPlayed; private void Start() { _rigidbody2D = GetComponent<Rigidbody2D>(); } private void Update() { Jump(); } private void Jump() { if (Input.GetKeyDown(KeyCode.Space) && _isGround) { AnimationJumpPlayed?.Invoke(); } } private void OnCollisionStay2D(Collision2D collision) { if (collision.collider.TryGetComponent(out Flour flour)) _isGround = true; } private void OnCollisionExit2D(Collision2D collision) { if (collision.collider.TryGetComponent(out Flour flour)) _isGround = false; }
Контролер преодоления бомб находится над объектом: если ты попадаешь в этот тригер, счетчик очков увеличивается на 1, но если у тебя не получилось перепрыгнуть, те игрок соприкасается с бомбой - игра заканчивается..

Для усложнения игры, я добавил метод, который на случайном значении очков дополнительно выбрасывает по одной бомбе,дополнительно к уже созданной. Но это еще не все, чем дальше вы заходите, тем быстрее будут двигаться объекты навстречу вам.
Заключение
В конечном итоге, проект получился играбельным, хоть и не очень оптимизированным, этим я хочу заняться в настоящее время, и поделиться с вами в следующей статье.
