Разработка своей Just Shapes & Beats и как всё началось +7


AliExpress RU&CIS

Немного о себе

Здравствуйте, мне 16 лет и я люблю играть в Just Shapes & Beats (JSAB). Одним прекрасным днём я узнал о такой игре, как JSAB. Я был очень поглощён геймплейной частью, разработчики создали больше 30 уровней из простых геометрических фигур - это же гениально! Но просто так играть мне не хотелось, мне хотелось создавать что-то своё. И так как у JSAB есть редактор уровней, но он находится в pre-alpha тестировании уже больше 2 лет, а уровни делать хочется, мною было принято решение создать свою JSAB. Теперь приступим к самому началу.

Самые начала начал

Так как я давно хотел сделать свою игру, но своих идей не было, я решил таки сделать клон JSAB, но внести туда что-то свое. Движок я выбрал конечно же Unity, так как уже давно им интересовался и имел хоть и небольшой, но хоть какой-то опыт работы с ним. JSAB я решил делать для мобильных устройств, так как и сам хотел играть везде, где бы я ни был. Изначально цветовая гамма моей игры не была похожа на оригинал, всё было монохромным.

Выглядело это всё таким образом. Также отличалось управление, игрок управлялся мышью либо касанием по экрану и не было возможности делать рывок.

Техническая часть

Приступим к технической части игры, и начнём с создания объектов.

Создание объектов

Все объекты создавались через Instantiate, что, как позже выяснилось, очень сильно бьёт по оптимизации. Просто представьте такую ситуацию

public GameObject Obj;

private void Start(){
  for(int i = 0; i < 100; i++){   
		GameObject.Instantite(Obj);
  }
}

Да, компьютер вывезет такие нагрузки, но телефону уже будет довольно тяжко. Позже я решил эту проблему использованием пула.

Также все объекты создавались просто в игровом мире, что конечно никуда не годилось. Позже я создал канвас, но об этом уже в другой части. Для создания объектов использовался JSON формат, в который я вручную записывал типы атак, время их появления и параметры. Файлик выглядел примерно так

{
  attacks: [
    {
      "attackType": "DotCircle",
      "time": "1,0828",
      "dotCount": "20"
    },
    {
      "attackType": "Beam",
      "time": "3,06713",
      "width": "50"
    }
  ]
}

При запуске игры этот JSON файл парсился в массив и через Update брал время каждой атаки и сравнивал его с текущим временем музыкального трека.

Анимации

Самой мучительной частью всей игры тогда и до сих пор были анимации. В самых ранних вариантах игры анимации я создавал через код, и сейчас их делаю так же, но по-другому. Все анимации были расписаны в коде в виде ключевых кадров. К сожалению кода не осталось, так бы я показал вам этот тихий ужас. Но вот пример из доков Unity

Animation anim = GetComponent<Animation>();
AnimationCurve curve;

// create a new AnimationClip
AnimationClip clip = new AnimationClip();
clip.legacy = true;

// create a curve to move the GameObject and assign to the clip
Keyframe[] keys;
keys = new Keyframe[3];
keys[0] = new Keyframe(0.0f, 0.0f);
keys[1] = new Keyframe(1.0f, 1.5f);
keys[2] = new Keyframe(2.0f, 0.0f); 
curve = new AnimationCurve(keys);
clip.SetCurve("", typeof(Transform), "localPosition.x", curve);

// update the clip to a change the red color
curve = AnimationCurve.Linear(0.0f, 1.0f, 2.0f, 0.0f);
clip.SetCurve("", typeof(Material), "_Color.r", curve);

// now animate the GameObject
anim.AddClip(clip, clip.name);
anim.Play(clip.name);

И здесь всего лишь прописана трансформация объекта по оси X и изменение его цвета.

Коллайдеры

Это вообще отдельная вещь, коллайдеры просто постоянно отказывались работать так, как надо. Это как раз можно увидеть здесь.

Лирическое отступление

Я очень долго провозился с кругом из точек, я просто перелопатил массу материала, но не мог найти ответы. В итоге оказалось, что можно просто использовать синусы и косинусы, но тут тоже были подводные камни. C# в функцию синуса и косинуса принимает значения в радианах. Я очень долго не мог понять в чём же именно проблема, так как давал значение в градусах. Мои точки никак не хотели лететь туда, куда надо, но позже узнал что и как работает. Чтобы перевести градусы в радианы нужно нашу градусную меру умножить на ? и разделить на 180, но ещё позже я выяснил, что в Unity уже есть готовое решение. Нужно градусную меру (AngleInDegree) умножить на переменную.

public float AngleInDegree = 90f;

private void Start(){
  float cos = Mathf.Cos(AngleInDegree * Mathf.Deg2Rad);
  float sin = Mathf.Sin(AngleInDegree * Mathf.Deg2Rad);
}

Начало "новой эпохи"

В конце концов монохромная палитра надоела глазу и было принято решение использовать оригинальную розово-голубую палитру. Также вся механика была переработана, я отказался от использования JSON в качестве файла уровня и перешёл на использование встроенного юнитевского таймлайна. На нём можно было создавать кастомные маркеры (материал, который я использовал, если вдруг понадобится). И я создал несколько маркеров, отвечающих за свои атаки. Также связал Playable (компонент таймлайна, который отвечает за проигрывание и т.д.) с AudioSource'ом (музыка) и в итоге всё это было синхронизировано.

В итоге вышла такая вот штука:

Небольшой итог

После добавления ещё нескольких атак, я создал наконец первый уровень, ну точнее сделал ремейк уровня Chronos (и то не полностью ремейк).

Я уже вовсю использовал возможности таймлайна, я подвязал нужные мне клавиши клавиатуры на нужные мне атаки и таким образом делал уровни. Также хочу сказать спасибо тем, кто это прочитал, надеюсь это было хоть немного интересно! Скоро будет вторая часть, в которой я уже расскажу о том, к чему я пришёл за почти 3 месяца разработки и немного о текущей стадии разработки. Также вы можете посетить мой канал, чтобы следить за процессом разработки, а также у меня есть дискорд cервер.




Комментарии (0):