Прототипирование игровых проектов на Unity3d

в 13:21, , рубрики: game development, Gamedev, gamedevelopment, prototyping, unity, unity3d, геймдев, Программирование, разработка, метки: , , , , ,

Так сложилось, что вот уже год как я проживаю в холодной Финляндии. Изначально приехал сюда учиться, но последние несколько месяцев активно подыскиваю себе работу: занимался массовой рассылкой своего резюме, посетил многие ивенты/конференции, побывал в нескольких офисах разных финских геймдев-контор. Коих, к слову, тут довольно много: благо, местная International Game Developers Association (в отличии от родной, украинской) живет, здравствует и собирает народ на халявное пиво раз в месяц. Так вот, я заметил, очень многие компании (вместительностью 10-20 человек) или переходят, или уже перешли на Unity3D.

Изначально статья планировалась как философское размышление на тему баланса что_прогер_пишет/что_игрок_видит, с примесями полезных сниппетов/хинтов по работе с Unity. На самом деле, во время выполнения тестового задания в одну из компаний, ко мне внезапно нагрянула муза написать подобную статью, посему я пока не знаю, что из этого выйдет.


Для начала, пару десятков слов о себе: уже пошел 10-й год, как я интересуюсь геймдевом — ровно 10 лет назад я склепал первую игру на Паскале, Sea Wars, ака морской бой. Занимался на любительском уровне, в основном в энтузиастксих проектах, пару раз работал в относительно крупных компаниях, набирался опыта. Работал со многими движками: сначала работал с 3D Gamestudio, Ogre, Irrlicht, Leadwerks, и прочими Torque. Unity3D я до этого года, правда, совсем не любил. После Global Game Jam — изменил мнение кардинально.

О учебе: закончил магистратуру в Киевском Политехническом, осознал, что уровень образования оставляет желать лучшего (в группе было всего 3 человека, заинтересованных в программировании), посему удачно захотел и не менее удачно поступил в Финский универ.

Вообще, о житии в Финляндии, универах и подробностях IGDA'вых попоек я расскажу в другой раз, пора переходить к геймдеву.

Тестовое задание было следующим: нужно было написать прототип для полета и посадки самолета, вид сбоку. Редактировать его положение (transform) напрямую — запрещено, можно только применять силы (force) и вращающие моменты (torque). Времени я попросил 2 дня, и задание таки закончил через 2 дня. Правда, еще несколько дней игрался с физикой, и через 4 дня отправил финальную версию, которая меня почти полностью удовлетворила.

Итак, мне в голову пришла такая критеризация кода:
1) много кода и временных затрат, для игрока эффект минимален
2) средне кода, эффект так себе
3) пару строк кода, эффект налицо, публика в шоке

1. Много кода, эффект почти незаметен / или на него не обращают внимания

Самая гемморная и неблагодарная часть. Без нее в игру никто играть не будет, но даже если она будет сделана на отлично, никто на это не обратит внимание: это в порядке вещей. А вот мелкие недочеты сразу бросаются в глаза. Короткое название "Она должна присутствовать, если ее нету — фейл".

Физику, к примеру, я переделывал с нуля несколько раз:
— сначала пробовал просто формулы и реальные значения массы/размаха крыльев/мощности двигателя, правда, позже все равно вводил свои коэффициенты. Для себя отмазался тем, что важны не точные значения, но порядок возрастания: например зависимость подъемной силы от скорости. В итоге, в формулах стало больше моих «открытий», чем реальных формул. Фейл.
— затем сделал суровое лицо, накачал совковских книг по аэродинамике, начал делать все по науке. Впрочем, результат был не намного лучше, так как своих добавлений стало относительно мало.
— полез гуглить подобные авиасимуляторы, поигрался чуток с JSBSim. Ничего удовлетворительного не нашел, но формулы на заметку взял.
— в этот раз я забил на науку и реалистичность, поставил самолету минимальный вес/размах/мощность и начал совмещать весь новоприобретенный опыт. В последний день, по совету друга-любителя ИЛ-2, добавил «клевание» носом, и в целом получилось очень даже мило.

Однако, весь этот труд, естественно, мало заметен при игре: так и должно быть, иначе зачем вообще проект показывать? Что, собственно, вполне логично.

Кусок кода оттуда (вся функция расчета физики довольно большая, приведу самую интересную часть). Комментариев в этом нелегком месте поставил побольше, чтоб ревьювер заценил :)

Я обычно пишу для Unity на шарпе, но попросили написать на JavaScript. Ну, JavaScript так JavaScript…

	//// Thrust force
		// Ft = const * p * n^2 * d^4, 			
		// where const = 1,3; p = 0.125; n = power; d = screw diameter (2,4 for F4U-1 Corsair)
		// Ft = 5.39 * n^2
		trustCoeff = rotorVelocity * power*power * powerCoeff;
		thrustVector = Vector3(1,0,0) * trustCoeff;  
		
		//// Angle of attack, Lift force
		// http://wright.nasa.gov/airplane/lifteq.html
		// http://wright.nasa.gov/airplane/incline.html
		// C = 2 * m * alpha
		// L = 1/2 * p * V^2 * A * C      , where p = 0.125 [kg * sec^2 / meter^4] at +15C; A = 9.172 for F4U-1 Corsair
		// L = 1.14 * V^2 * (m * alpha)	
		speedWeight = 0.0125 * (velocityForwardVectorSqr/2);
		liftCoeff = wingspan * attackAlpha * speedWeight * weightCoeff;
		liftVector = Vector3(0,1,0) * liftCoeff;	
		
		//// Air resistance = base resistance + inductive resistance
		// http://en.wikipedia.org/wiki/Parasitic_drag
		// http://en.wikipedia.org/wiki/Lift-induced_drag
		// resistBasic = Const * (p * V^2 * S) / 2 = Const' * V^2 * S
		// resistInductive = liftForce^2 / (p * V^2/2 * S)
		dragCoefficient = 2*airDrag + 2 * airDrag * horizonAngle * wingspanCoeff;
		dragVector = - airSpeedVector * dragCoefficient;
	

В последний момент меня еще и порисовать пробило. Так что у вас появляется эксклюзивная возможность насладиться моими умениями :)
Сильно не бить, я не художник.

Прототипирование игровых проектов на Unity3d

2. Средне кода, эффект так себе

Самая средняя и невзрачная часть. Короткое название "Если есть — хорошо, если нету — ну и ладно". Сил тратится средне… хм, а еще дает небольшой полет для фантазии.

Муза стукнула по столу кулаком, и сказала делать Решил я немного выпендриться и сделать процедурную генерацию ландшафта. В данном случае он бывает 2 типов: океан или земля. Земля реализована в майнкрафтовском стиле, из кубиков. Даже не знаю, какой кусок кода привести так, чтоб было не очень долго, но интересно. Делал, кстати, в предпоследний вечер, на ночь глядя, так что рефакторить есть куда.

	
	var firstIslandLength: int = Random.Range(70, 130); // width of island
		generationDist = 0;
		GenerateIsland(generationDist, firstIslandLength);
		
		var firstOceanLength: int = Random.Range(50, 100);
		generationDist += firstIslandLength + firstOceanLength;
		GenerateOcean(generationDist, firstOceanLength);
		
		var secondIslandLength: int = Random.Range(10, 30);
		generationDist += firstOceanLength + secondIslandLength;
		GenerateIsland(generationDist, secondIslandLength);
		
		var secondOceanLength: int = Random.Range(100, 150);
		generationDist += secondIslandLength + secondOceanLength;
		GenerateOcean(generationDist, secondOceanLength);
		
		var thirdIslandLength: int = Random.Range(70, 80);
		generationDist += secondOceanLength + thirdIslandLength;
		GenerateIsland(generationDist, secondOceanLength);
		GenerateTargetObj(generationDist, secondOceanLength);
	}

	function GenerateOcean(pos: int, length: int)
	{
		var newOcean = Instantiate(waterObject, Vector3(pos - 5, -2, 50), Quaternion.identity); 
		newOcean.transform.localScale.x = length/4;
		Debug.Log("Ocean. Pos: " + pos + ". Length: " + length);
	}
	

Схема будет примерно такая:
Прототипирование игровых проектов на Unity3d

3. Пару строк кода, эффект налицо

Самая важная и интересная часть данного опуса, особенно для тех, кто делает первые-вторые-третьи шаги в геймдеве и прототипировании. И для тех, кто ждал хинтов по Unity3d. Короткое название "Если она есть — круто, если ее нету — проект выглядит сырым".

В Unity:
— Импортируем пак со скайбоксами (Assets/Import package/skyboxes).
— Создаем новый объект (Game Object/Create Empty), можно взять уже существующий.
— Создаем новый скрипт SkyboxControl
— В скрипт записываем целых 3 строки

	var skyboxMaterials: Material[];
	function Start () 
	{	
		RenderSettings.skybox = skyboxMaterials[Random.Range(0, skyboxMaterials.length - 1)];
	}
	

— Перетаскиваем скрипт на новоиспеченный объект, жмем на стрелочку возле Skybox Materials, вводим число, например 4: создается и открывается массив из 4 элементов
— Открываем Standard Assets/Skyboxes и заполняем вышеуказанный массив любыми скайбоксами на выбор

Что получаем? На действия потрачена 1 минута (это вместе с отхлебнуть пивка и почухаться), а счастливый юзвер каждый новый перезапуск игры будет наблюдать новый случайный скайбокс.

Еще пример: звук. В моем случае, у меня был звук вращающегося пропеллера, я захотел его красиво продемонстрировать.
Пожалуйста:
— Кидаем звук на озвучиваемый объект
— В недрах Тундры, выдры в гетрах скрипта, где-то в функции Update() прописываем аж 1 строку

soundPlayer.audio.pitch = rotorVelocity;

rotorVelocity — это управляемая игроком скорость вращения винта, меняется на интервале [0..1], зависит от того, как долго юзверь жмет кнопку.

Все, получаем профит. Чем больше будет значение скорости вращения мотора, тем быстрей будет проигрываться звук. Дело половины минуты (вместе с допиванием пива).

Прототипирование игровых проектов на Unity3d

Вывод

Не забывайте о таких мелочах. Они делаются довольно быстро (в частности, в Unity3d), а пользы проекту приносят много.

PS: да, не верьте, когда на геймдев конкурсах, или на тестовых заданиях говорят, что графика — не важно. Графика — очень важно, если геймплей не гениальный (что встречается крайне редко, но зато заметен сразу — привет Нотчу). К тому же, ее можно сделать крайне быстро, а проект будет намного казаться законченней.

PPS: и еще одно: если интересно, обязательно зацените эту презентацию. Никакой рекламы: я тех парней вообще в первый раз в жизни вижу. Но дело говорят.

PPPS: в ту компанию так и не взяли. Посему, выкладываю линк на то, что вышло. Реализация мне, в принципе, нравится — переделаю физику еще разок (или доведу эту до кондиции), сделаю пару десятков уровней, да попробую зарелизить на какой-нибудь портал Unity игр. Да, я всегда открыт для конструктивной критики.

Автор: VeTaLv


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js