Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 909 сообщений
Cообщения с меткой

unity - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

Как С# разработчику перейти на Unity

Четверг, 10 Августа 2017 г. 18:57 (ссылка)

Unity3D — один из самых популярных игровых движков. В последние годы всё больше отличных игр выходят благодаря тому, что Unity прост в использовании и предлагает разработчикам много готовых решений. Алексей Науменко, .NET Developer в Plarium Kharkiv, рассказал с чего разработчику начать изучение Unity.







Как я начал программировать



Я учился в ХАИ по специальности «Телекоммуникации». У нас был преподаватель, который конструировал беспилотники. Благодаря ему уже на 4-м курсе я начал писать простой код на С для микроконтроллеров, которые управляют передачей данных с земли на БПЛА. Тогда я решил, что нужно выучить какой-то актуальный язык программирования, чтобы писать на нём постоянно, а не только для решения узких задач.



Выбирал я между С# и Java: читал книги по этим языкам, но потом просто открыл Visual Studio и Java IDE и сделал выбор в пользу первого по «обертке». Не самый правильный способ анализа преимуществ и недостатков, но о выборе я не жалею.



Почему пошел в геймдев и выбрал Unity



В 5–7 классах мы с другом пытались сделать игру. И хотя получилась ерунда, романтика процесса осталась со мной. К тому же я люблю играть, особенно в древние RPG. После университета я работал в нескольких продуктовых компаниях: год занимался веб-программированием, потом 4 года разрабатывал ПО для call-центров. Но меня всё время преследовала идея попробовать себя в разработке игр. Так что в свободное от работы время я стал думать, какой движок использовать для будущей игры.



Многие разработчики используют Unity и Unreal Engine, но я хотел изучить все варианты. Поэтому я стал разбираться, на чем написаны популярные проекты. Оказалось, что это либо самописные движки, как, например, у Naughty Dog, либо движки, о которых очень мало информации в интернете — чтобы работать с ними, нужно, скорее всего, некоторое время работать в индустрии и знать хотя бы общие принципы построения игровых движков.



Я вернулся к выбору между Unity и Unreal Engine. И так как на тот момент я уже 4 года программировал на .NET, выбор был прост: в Unity есть C#, а в Unreal Engine — нет. Еще один плюс Unity: я погуглил некоторые интересные мне вопросы и почти на все из них нашел попытки ответить. Пусть не всегда профессиональные, но информация была, и было с кем ее обсудить.



У Unity есть аналог StackOverflow — Unity Answers. Там очень просто найти ответы на конкретные вопросы на начальном этапе, поэтому порог входа очень низкий, особенно если человек понимает хотя бы общие принципы программирования.



С чего начать обучение



Я изучал уже решенные задачи, похожие на те, что интересовали меня. Однажды я искал конкретное решение, но не нашел его в Asset Store. Поэтому начал мониторить форумы и наткнулся на парня, который делал именно то, что мне было нужно, но в Store его решение не пропустили по каким-то требованиям. Я написал ему сообщение и предложил купить его наработку. Он очень обрадовался возможности подзаработать — это был румынский десятиклассник. Чуть ли не лучшее мое вложение в изучение движка: 10$ плюс столько же за Swift-платеж.



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



Всегда лучше ориентироваться на какой-то пример. Я распотрошил покупку: там было много наворочено, но я переделал это решение под свои нужды. Пока разбирал этот пример, многие вопросы начального уровня отпали. Так начал понимать основные принципы работы с Unity и продолжил разбираться с возможностями движка.



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



Нет смысла изучать Unity просто так — стоит начинать с решения конкретных проектных задач. Лучше сразу определиться: «Я хочу сделать Pac-Man». Начинаешь думать, что для этого понадобится: например, нужно реализовать управление персонажем. Желтое существо ест белые точки. Существо должно понимать, что наткнулось на съедобный объект — значит, нужно начать с определения соприкосновения съедобной точки с Пакменом. Тогда появляется конкретная проблема и необходимость искать пути ее решения — а это, по-моему, и есть лучший способ изучения технологии.



Переход с .NET на Unity на практике



Когда мы собеседуем кандидатов, прямо говорим, что не проверяем знания Unity, а фокусируемся на .NET. На практике мы убедились: человека, который знает .NET, гораздо легче обучить работе с движком, чем того, кто начал изучать язык параллельно с Unity. Поэтому приглашаем на собеседования людей, которые знают .NET и просто хотят работать на Unity. Дальше всему обучим.



Иногда мы собеседуем Senior или Middle+ .NET программистов, которые не знакомы с Unity вообще. При этом человек не переходит на позицию Junior, потому что в Plarium, да и в работе с движком, нет понятия Unity Junior. Если с .NET всё хорошо, освоить движок будет очень просто.



Что почитать



Кроме Unity Answers есть еще UnifyWiki. Можно декомпилировать код и посмотреть результат (он не обфусцирован).



На старте очень пригодились форумы (answers.unity3d.com и forum.unity3d.com). Также я читал книгу Game Engine Architecture Джейсона Грегори. Автор в ней не говорит конкретно о Unity, но подробно рассматривает составные части и особенности игровых движков в целом. Он в деталях описывает, из чего состоит движок, какая математика нужна, как устроен рендеринг. Эта книга расширяет представление о Unity: я начал понимать, что в этом движке есть или должно быть, что с него спрашивать. Единственная трудность — для прочтения этой книги нужно быть очень мотивированным: она не нудная, но достаточно объемная.



Преимущества работы с Unity



Большие компании любят Unity за кроссплатформенность. Если ты что-то написал, оно билдится и под iOS, и под Android — пусть и с надстройками, но зато сразу работает без особых плясок. Конечно, если это не касается платежки :)



В нашем случае преимущество также в том, что Plarium — официальный партнер Unity с поддержкой уровня Enterprise Support. Нам не только быстро отвечают на запросы, но и предоставляют больше открытого кода, и мы можем сами что-то вскрыть и допилить.



Надеюсь, информация будет полезна тем, кто планирует работать с Unity. Успехов!
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/335370/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

5 бесплатных ассетов для Unity3D, которые облегчат процесс разработки

Среда, 05 Июля 2017 г. 14:01 (ссылка)

Недавно мы выпустили обзор некоторых Unity ассетов для начинающего 2D разработчика.

Сегодня предлагаем вашему вниманию подборку из 5 бесплатных ассетов для Unity3D, максимально простых в использовании и полезных в работе. Данные ассеты призваны упростить некоторые аспекты разработки, а также сэкономить вам время за счет автоматизации определенных нудных задач.







Autosaver



Autosaver – очень полезный ассет для тех, кто ценит свое время. Решение поможет сохранять проект автоматически, не позволяя случиться страшному. Ведь всегда есть риск потерять значительное количество изменений в проекте и тем самым убить впустую кучу времени и трудов.



Для того чтобы просмотреть параметры сохранения, зайдите в File/Preferences/Autosave

В меню «Настройки» доступны следующие параметры:




  • Включение/Выключение

  • Сообщения о сохранении в консоли

  • Временной интервал, через который будет производиться сохранение (от одной до тридцати минут)

  • Сохранение ассетов

  • Сохранение каждой новой сцены

  • Сохранение после определенного количества изменений в окне иерархии









PlayersPrefs Editor and Utilities



Небольшой ассет, способный облегчить работу с PlayersPrefs в Unity. Он позволяет просматривать в окне редактора все сохраненные ключи и их значения. Также можно добавлять новые Players-ы и редактировать значения во время выполнения.



PlayersPrefs Editor and Utilities включает в себя поддержку шифрования для защиты от случайного взлома. Для записи и чтения шифрованных данных используйте следующий код:







Окно редактора PlayersPrefs выглядит так:







И вишенка на торте: через класс PlayerPrefsUtility можно записывать значения Bool, DateTime, TimeSpan, Enum:







Simple Note



Нередко нам приходится тратить много времени на то, чтобы разобраться в решении другого разработчика, а иногда и в своем собственном по прошествии долгого времени.



Чтобы свести такие ситуации к минимуму, на помощь приходит Simple Note. Ассет предназначен для создания заметок прямо в редакторе. Эта возможность особенно ценна, если разработку одновременно ведут двое и более человек.



Как можно догадаться по названию, ассет очень прост в использовании, но при этом имеет массу преимуществ.



Функционал Simple Note включает:



1. Глобальный редактор заметок SimpleNote

Здесь можно добавлять и редактировать общие заметки. Окно вы найдете в меню Window/SimpleNote/ShowNotes







2. Заметки для GameObject – отображаются в окне Scene, когда объект выделен:







Добавить заметку непосредственно на нужный объект можно через меню GameObject/SimpleNote/Add Or Remove Note.



3. Заметки для скриптов в инспекторе:







Для использования нужно добавить атрибуты:







Также в меню File/Preferences/SimpleNote есть возможность задать следующие настройки для отображения заметок:




  • Отступ от края, сторона отображения заметки в окне Scene

  • Цвет отображения заметок









Inspector Navigator



Этот ассет может быть весьма полезен при работе с большим количеством объектов на сцене. Сами знаете, сколько времени можно убить просто копаясь в иерархии сцены или проекта в поисках объекта, который вы редактировали минуту назад.



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



Также Inspector Navigator может сохранять историю изменений. Так что при переходе между сценами или после перезапуска проекта можете быть спокойны: все сохранится в должном виде.







Ez Files Renamer



Ez Files Renamer поможет держать имена объектов в чистоте и порядке.



Просто выделите нужные объекты в окне иерархии или проекта, заполните строку New Name – и готово! Кроме того, можно добавлять префиксы и выбирать знак разделяющий имя с префиксом. Пронумеруйте объекты, установите знак разделения для нумерации. Это прекрасно работает как в окне иерархии, так и в окне самого проекта и не отанимает много времени.



В дополнение можно сказать, что в ассете есть функция упорядочивания объектов по разным признакам: по нумерации (возрастание и убывание) и по позиции (возрастание и убывание).



Для того чтобы открыть окно Ez Files Renamer, пройдите по следующему пути: Window/BDOAssets/ EzFilesRenamer







Вот те инструменты, полезность которых мы оценили на практике. Если у вас в арсенале тоже есть полезные ассеты, которые помогут сделать работу над проектами удобнее, поделитесь ими в комментариях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/332172/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Создание шейдерного эффекта 3D-принтера

Понедельник, 26 Июня 2017 г. 13:15 (ссылка)

В этом туториале мы воссоздадим эффект 3D-принтера, используемый в таких играх, как Astroneer и Planetary Annihilation. Это интересный эффект, показывающий процесс создания объекта. Несмотря на внешнюю простоту, в нём есть множество далеко не тривиальных сложностей.







Введение: первая попытка



Для воссоздания этого эффекта давайте начнём с чего-нибудь попроще. Например, с шейдера, по-разному раскрашивающего объект в зависимости от его положения. Для этого необходимо получить доступ к положению отрисовываемых пикселей в мире. Это можно выполнить, добавив поле worldPos к структуре Input поверхностного шейдера Unity 5.



struct Input {
float2 uv_MainTex;
float3 worldPos;
};


Затем можно использовать в функции поверхности координату Y положения в мире для изменения цвета объекта. Этого можно добиться изменением свойства Albedo в структуре SurfaceOutputStandard.



float _ConstructY;
fixed4 _ConstructColor;

void surf (Input IN, inout SurfaceOutputStandard o) {

if (IN.worldPos.y < _ConstructY)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
else
{
o.Albedo = _ConstructColor.rgb;
o.Alpha = _ConstructColor.a;
}

o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
}


Результатом становится первое приближение к эффекту из Astroneer. Основная проблема заключается в том, что для цветной части всё ещё выполняется затенённое отображение.



image



Неосвещённый поверхностный шейдер



В предыдущем туториале PBR and Lighting Models мы изучали способ создания собственных моделей освещения для поверхностных шейдеров. Неосвещённый шейдер всегда создаёт один и тот же цвет, вне зависимости от внешнего освещения и угла обзора. Можно реализовать его следующим образом:



#pragma surface surf Unlit fullforwardshadows
inline half4 LightingUnlit (SurfaceOutput s, half3 lightDir, half atten)
{
return _ConstructColor;
}


Его единственная задача — возвращать единственный сплошной цвет. Как мы видим, он обращается к SurfaceOutput, который использовался в Unity 4. Если мы хотим создать собственную модель освещения, работающую с PBR и глобальным освещением, то нужно реализовать функцию, получающую в качестве входных данных SurfaceOutputStandard. В Unity 5 для этого используется следующая функция:



inline half4 LightingUnlit (SurfaceOutputStandard s, half3 lightDir, UnityGI gi)
{
return _ConstructColor;
}


Параметр gi здесь относится к глобальному освещению (global illumination), но в нашем неосвещённом шейдере он не выполняет никаких задач. Такой подход работает, но у него есть большая проблема. Unity не позволяет поверхностному шейдеру выборочно изменять функцию освещения. Мы не можем применить стандартное освещение по Ламберту к нижней части объекта и одновременно сделать верхнюю часть неосвещённой. Можно назначить единственную функцию освещения для всего объекта. Мы должны сами менять способ рендеринга объекта в зависимости от его положения.



image



Передаём параметры функции освещения



К сожалению, функция освещения не имеет доступа к положению объекта. Простейший способ предоставить эту информацию — использовать булеву переменную (building), которую мы зададим в функции поверхности. Эту переменную может проверять наша новая функция освещения.



int building;
void surf (Input IN, inout SurfaceOutputStandard o) {

if (IN.worldPos.y < _ConstructY)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;

building = 0;
}
else
{
o.Albedo = _ConstructColor.rgb;
o.Alpha = _ConstructColor.a;

building = 1;
}

o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
}


Расширяем стандартную функцию освещения



Последняя проблема, с которой нам предстоит столкнуться, довольно сложна. Как я объяснил в предыдущем разделе, мы можем использовать building для изменения способа вычисления освещения. Часть объекта, которая в текущий момент строится, будет неосвещённой, а на оставшейся части будет правильно рассчитанное освещение. Если мы хотим, чтобы наш материал использовал PBR, мы не можем переписывать весь код для фотореалистичного освещения. Единственное разумное решение — вызывать стандартную функцию освещения, которая уже реализована в Unity.



В традиционном стандартном поверхностном шейдере директива #pragma, определяющая использование функции освещения PBR, имеет следующий вид:



#pragma surface surf Standard fullforwardshadows


По стандартам наименования Unity легко заметить, что используемая функция должна называться LightingStandard. Эта функция находится в файле UnityPBSLighting.cginc, который можно при необходимости подключить.



Мы хотим создать собственную функцию освещения под названием LightingCustom. В обычных условиях она просто вызывает стандартную функцию PBR из Unity под названием LightingStandard. Однако при необходимости она использует определённую ранее LightingUnlit.



inline half4 LightingCustom(SurfaceOutputStandard s, half3 lightDir, UnityGI gi)
{
if (!building)
return LightingStandard(s, lightDir, gi); // Unity5 PBR
return _ConstructColor; // Unlit
}


Чтобы скомпилировать этот код, Unity 5 нужно определить ещё одну функцию:



inline void LightingCustom_GI(SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi)
{
LightingStandard_GI(s, data, gi);
}


Она используется для вычисления степени воздействия освещения на глобальное освещение, но для целей нашего туториала она необязательна.



Результат выйдет точно таким, какой нам нужен:



image



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



Отрезаем геометрию



Проще всего добавить к нашему шейдеру эффект прекращения отрисовки верхней части геометрии. Для отмены отрисовки произвольного пикселя в шейдере можно использовать ключевое слово discard. С его помощью можно отрисовывать только границу вокруг верхней части модели:



void surf (Input IN, inout SurfaceOutputStandard o)
{
if (IN.worldPos.y > _ConstructY + _ConstructGap)
discard;

...
}


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



Cull Off


image



Теперь нас больше всего не устраивает то, что объект выглядит полым. Это не просто ощущение: в сущности, все 3D-модели являются полыми. Однако нам нужно создать иллюзию, что объект на самом деле сплошной. Этого с лёгкостью можно добиться, раскрашивая объект изнутри тем же неосвещённым шейдером. Объект по-прежнему полый, но воспринимается заполненным.



Чтобы достичь этого, мы просто раскрашиваем треугольники, направленные к камере обратной стороной. Если вы незнакомы с векторной алгеброй, то это может показаться достаточно сложным. На самом деле, этого можно довольно просто добиться с помощью скалярного произведения. Скалярное произведение двух векторов показывает, насколько они «сонаправлены». А это непосредственно связано с углом между ними. Когда скалярное произведение двух векторов отрицательно, то угол между ними больше 90 градусов. Мы можем проверить наше исходное условие, взяв скалярное произведение между направлением взгляда камеры (viewDir в поверхностном шейдере) и нормалью треугольника. Если оно отрицательное, то треугольник повёрнут от камеры. То есть мы видим его «изнанку» и можем отрендерить её сплошным цветом.



struct Input {
float2 uv_MainTex;
float3 worldPos;
float3 viewDir;
};

void surf (Input IN, inout SurfaceOutputStandard o)
{
viewDir = IN.viewDir;
...
}

inline half4 LightingCustom(SurfaceOutputStandard s, half3 lightDir, UnityGI gi)
{
if (building)
return _ConstructColor;

if (dot(s.Normal, viewDir) < 0)
return _ConstructColor;

return LightingStandard(s, lightDir, gi);
}


Результат показан на изображениях ниже. Слева «изнаночная геометрия» отрендерена красным. Если использовать цвет верхней части объекта, то объект больше не выглядит полым.



image



Эффект «волнистости»



image



Если вы играли в Planetary Annihilation, то знаете, что в шейдере 3D-принтера используется эффект небольшой волнистости. Мы тоже можем его реализовать, добавив немного шума к положению отрисовываемых пикселей в мире. Этого можно добиться или текстурой шума, или с помощью непрерывной периодической функции. В коде ниже я использую синусоиду с произвольными параметрами.



void surf (Input IN, inout SurfaceOutputStandard o)
{
float s = +sin((IN.worldPos.x * IN.worldPos.z) * 60 + _Time[3] + o.Normal) / 120;

if (IN.worldPos.y > _ConstructY + s + _ConstructGap)
discard;

...
}


Эти параметры можно подправить вручную для получения красивого эффекта волнистости.



image



Анимация



Последняя часть эффекта — это анимация. Её можно получить, просто добавив к материалу параметр _ConstructY. Об остальном позаботится шейдер. Можно управлять скоростью эффекта или через код, или с помощью кривой анимации. При первом варианте вы можете полностью контролировать его скорость.



public class BuildingTimer : MonoBehaviour
{
public Material material;

public float minY = 0;
public float maxY = 2;
public float duration = 5;

// Update is called once per frame
void Update () {
float y = Mathf.Lerp(minY, maxY, Time.time / duration);
material.SetFloat("_ConstructY", y);
}
}


image



Замечу в конце, что использованная в этом изображении модель несколько секунд выглядит полой, потому что нижняя часть ускорителей незамкнута. То есть объект на самом деле полый.



[Можно скачать пакет Unity (код, шейдер и 3D-модели), поддержав автора оригинала статьи десятью долларами на Patreon.]
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331576/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Из песочницы] Google Play и 2K установок в сутки без денежных вложений (+ статистика и доходы)

Вторник, 20 Июня 2017 г. 17:14 (ссылка)





Всем привет! Решил я поделиться с Вами опытом «бесплатного пиара» в Google Play, а именно способами для достижения 2K установок в день без денежных вложений. Вся статистика прилагается +информация о доходах



Сразу оговорюсь, это мои личные наблюдения и предположения, вся статистика собрана с моих приложений. Я не особо разбирался в тонкостях GP, поэтому могу быть и не прав.



Статистика, указанная в статье, собрана с нового приложения, которое живет с 24 мая 2017


Стоит упомянуть, что немалую роль играет ASO оптимизация, поэтому изначально придумывайте потенциально эффективные названия и описания вашим приложениям.



Бесплатное продвижение в Google Play



Начнем с того, что первые пару недель количество установок приложения обычно составляет 10 — 50 в сутки, и как показывает практика, это нормально. По прошествии 1/2/3 недель такого унылого хода, установки начинают расти. К примеру, в моем первом приложении, после застоя в пару недель, количество установок в день составляло около 500 — 1000.



Для достижения более 2К скачиваний на GP я предпринял действия описанные ниже:



1. Просьба поставить оценку приложению



Где-то вычитал, что оценки в GP не влияют на рост инсталлов приложения, но и черт бы с ним, мы же будет опираться на психологию. С большей вероятностью пользователь установит то приложение, у которого больше всего оценок, и что немаловажно положительных.



Я считаю, что игроку необходимо напомнить поставить оценку, да и еще дать за это какой-нибудь бонус, что послужит еще большим стимулом к хорошей оценке. Важно преподнести бонус не как поощрение за хорошую оценку, а как «извинение» за прерванный игровой процесс. Где-то я слышал, что в GP нельзя призывать игрока ставить хорошую оценку за награду, может я и неправ. Статья о просьбе поставить оценку





Статистика оценок в приложении с напоминанием



2. В игре должен быть контент для продаж

Вкладка Источники трафика -> Отчеты по источникам трафика



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





Пример: показатели коэффициента конверсии



3. Следуйте советам по оптимизации

Вкладка Источники трафика -> Советы по оптимизации



Следуйте советам по оптимизации, это поможет адаптировать приложение к юзерам из других стран.





Окно советов от GP



4. Запускайте эксперименты



Может это совпадение, а может и работающая тактика, которой надо придерживаться, но факт остается фактом, как только игра начинает набирать хоть какие-то обороты, необходимо запускать A/B тестирование с 1 — 2 или более вариантами. Видимо, гугл дает фору приложениям с A/B тестированием, и это нам на руку.



По появлению первых результатов тестирования, один из участников группы скинул мне скрин, на котором приложение было на первой полосе в разделе «Свежие релизы — рекомендуем». Совпадение? не думаю.





Результаты 3х дневного тестирования



Немного статистики о доходах



Статистика доход с рекламы AdMob







Статистика доход с продаж в приложении







Статистика установок







Спасибо за внимание, и удачи Вам с продвижением Ваших проектов!



P.S. Это моя самая первая статья, которую я когда-либо писал. Прощу прощения, если мой текст кому-то режет глаз.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/331294/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Топ 15 бесплатных Unity ассетов для начинающего 2D разработчика

Среда, 14 Июня 2017 г. 14:14 (ссылка)

Введение



Unity3D – безумно удобная среда, которая многое делает за нас. Именно поэтому она сейчас так востребована: разработка игр при правильном подходе становится не сложнее сборки конструктора.



Сама платформа Unity предоставляет широкий набор инструментов, но иногда не хватает и их. Тогда в дело вступает Asset Store с миллионами ассетов, моделей и примеров проектов.







Если у вас еще мало опыта в разработке приложений, имейте в виду: Asset Store – это огромный склад велосипедов, которые уже изобрели до вас. При этом там можно найти очень много бесплатного контента, или же контента по цене одной чашки кофе (сэкономьте на латте!).



Почему мы посвятили статью именно 2D играм? Посмотрите на рынок: 2D игры сейчас переживают ренессанс. Чтобы в этом убедиться, достаточно взглянуть на инди-сектор в Steam, Ketchapp и Zeptolab в мобильной разработке. 2D игры давно превратились из отжившего свое сектора в отдельную процветающую нишу рынка. Поэтому если вы решили делать 2D игру на Unity, сначала убедитесь, что у вас в арсенале есть все нужные инструменты, чтобы обеспечить должное качество продукта.



Немного про Asset Store



Если вы читаете эту статью, то скорее всего что-то слышали про Asset Store. Там хранятся несколько тысяч моделей, плагинов, систем частиц, скриптов и многое другое. Часть этого добра распространяется за деньги, а часть совершенно бесплатно! И мы настоятельно рекомендуем пользоваться этим обстоятельством. Прежде чем реализовывать A* для ваших юнитов, подумайте: может быть, кто-то уже сделал это до вас и выложил в общий доступ в удобной форме.



Ассеты с точки зрения 2D разработки



Так как мы рассматриваем 2D направление, модели, скрипты для камеры, скайбоксы и подобное отсекается сразу. Естественно, найдется разработчик, который сможет применить эти вещи в 2D игре, но статья предназначена в первую очередь для начинающих, которым в таких проектах лишние сложности не нужны.



Что же нам может понадобиться? Вот список:




  • Готовые шаблоны проектов, с помощью которых можно быстро научиться базовым механикам создания игры. Это могут быть как платформеры, так и что-то более специфическое, например, roguelike.

  • Так называемые Sprite packs, то есть паки текстур для вашей 2D игры. Они очень полезны на том этапе, когда у вас еще нет арта, но уже появились идеи для механики. Спрайт паки можно использовать, просто чтобы было с чем работать. Естественно, в релизной версии их лучше заменить на оригинальную графику.

  • Готовые 2D объекты. Это могут быть как классические триггеры (зоны смерти, точки респауна, телепорты), так и что-то более интересное, скажем, физически верно рассчитанный меховой шарик.

  • Скрипты и расширения редактора. Это отдельный, огромный класс компонентов, которые могут выполнять широкий спектр разных задач. Можно поставить скрипт, который добавит несколько приятных визуализаций в редактор, а можно превратить Unity в инструмент визуального кодинга, вроде Unreal Blueprints.

  • Эффекты. Сюда можно отнести огромные паки частиц, эффекты на камеру, шейдеры для спрайтов и т.п. В этом сегменте попадается особенно много бесплатных ресурсов.

  • Анимации. Сюда можно отнести библиотеку простых анимаций (твинов), а также примеры покадровой или скелетной анимации.





Непосредственно ТОП



1. Standard Assets



Пак стандартных ассетов от самой Unity. Это самые необходимые и проверенные в деле ассеты. Все они относятся к следующим категориям: 2D, Cameras, Characters, CrossPlatformInput, Effects, Environment, ParticleSystems, Prototyping, Utility, Vehicles. Эти ассеты можно подключить при установке Unity.



2. LeanTween



Великолепная библиотека твинов. Содержит все необходимые виды твинов (move, scale, rotate, alpha, color). Ее отличает очень удобный вызов методов, поддержка easing type и многое другое. Комбинируя простые твины, можно создавать очень интересные эффекты.



3. Simple Sprite Packer



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



4. Advanced Polygon Collider



Очень мощный инструмент для работы с полигон-коллайдерами. Позволяет более тонко настраивать количество вершин, работать с ними в рантайме.







5. 2D Platformer



Более сложный пример 2D платформера от самой Unity. В отличии от 2D Platformer Controller здесь добавлена анимация, стрельба и еще множество функций и объектов.



6. 2D Platformer Controller



Ассет, который содержит в себе все необходимое для создания платформера. Здесь есть скрипты, управление персонажем, работа с камерой, вся необходимая физика и механика различных платформ. Очень рекомендуем посмотреть на этот ассет, прежде чем приступать к своему проекту.



7. Collider2D Optimization



Небольшое улучшение для ваших полигон-коллайдеров. С этим ассетом они становятся более плавными и… более тяжелыми с точки зрения производительности. Но если вам нужны точные формы коллайдеров, то этот ассет для вас.







8. Unity Anima2D



Большой ассет для работы с скелетной 2d анимацией, включая инверсную кинематику и автоматическую генерацию весов. Раньше он стоил 60 $, но недавно Unity сделала его бесплатным. Очень мощный инструмент.



9. 2D Tilezone Lite



Удобный ассет-редактор для создания тайловых уровней; может разбивать атласы по сетке, рисовать уровни в редакторе Unity, добавлять коллайдеры на блоки и настраивать слои отрисовки.



10. Localization



Достаточно удобная и простая система локализации. Не подойдет для больших игр, но в маленьких проектах отлично справляется с заменой текста на разных языках.



11. AutoSave



AutoSave – ассет, который не ценишь, пока он не сработает. Суть в том, что при обычном положении вещей если Unity зависает или вылетает, а вы не сохранили сцену, то все внесенные изменения пропадут. То есть вы можете час делать уровнь, забыть сохраниться и потерять его из-за критической ошибке в скрипте (например, бесконечного цикла). AutoSave сохраняет сцену при каждом нажатии на кнопку Play. Это очень удобно.



12. Particle pack



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



13. 2D Roguelike



Мощный шаблон «рогалика». Содержит в себе управление героем, врагов, этажи уровней, звуки и эффекты.



14. TexturePacker Importer



Расширенный и усиленный вариант Simple Sprite Packer. Огромное количество функционала для работы с атласами.







15. Light2D — GPU Lighting System



Интересный ассет для создания красивой 2D системы освещения с контрастными тенями. Хорошо подойдет если вы делаете тактическую игру, стэлс платформер или какой-нибудь хоррор. Подобный ассет добавит в вашу игру атмосферы.



Заключение



Разумеется, у каждого ассета из этого списка есть свои альтернативы, и, возможно, вы где-то не согласитесь с нашим выбором. Это нормально, если учесть, что в Asset Store несколько тысяч ассетов. Поэтому обязательно делитесь своими предложениями в комментариях.
Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330848/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
ferderfre

В ЮАР убили больных львов из цирка ради ингредиентов для знахарского зелья

Вторник, 06 Июня 2017 г. 22:03 (ссылка)

­­­­­­­­­­­­­­­­­­­­­­­­В ЮАР убили львoв Хосе и Лисо, которых защитники живoтных спасли из цирка в Южной Америке. Об этом сообщает BBC News.

Трупы львoв со снятыми шкуpами были найдeны в частном заповеднике Эмойя на северe пpовинции Лимпопо.

«Этот случай — нe обычное бpаконьерствo», — цитирует The Daily Telegraph слова Минунeтты Хеузер (Minunetta Heuser), котоpая заведует Эмойей вместе с дочерью. У зверeй были отрeзаны головы, хвoсты и лaпы. Это дает повoд для подозрeний, что убийства были совершены в ритуальных целях. Знаxари нeредко используют львиные лaпы в свoих зельях.

Материалы по теме

00:03 — 18 февpаля

«Енот ослеп, от нeго попытались избавиться»

Что ждeт зверeй, попавших в контактный зоопарк

Год назад междунаpодная организация Animal Defenders International (ADI) нашлa Хосе и Лисо в цирке в Лиме. Зверeй дeржали в маленьких грязных клетках и постоянно били. При содeйствии влaстей Перу хищников удалось освoбодить. Их пeревезли в Африку и поселили в Эмойе.

Защитники живoтных из ADI занимаются пeреселением спасенных живoтных в Африку в течение 21 года. Только в 2016 году они отпpавили туда 33 льва из цирков в Перу и Колумбии. В организации утверждают, что их подопeчные впeрвые стали жертвами бpаконьеpов. ADI pассматривает вoзможность объявления вoзнагpаждeния за информация, котоpая поможет найти убийц Хосе и Лисо.

В марте сообщалось, что Бpаконьеры пpоникли в зоопарк гоpода Туари в 50 километpах к западу от Парижа, гдe вечеpом 6 марта застрeлили белого носоpога по имени Винс pади рeдкого pога.

Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Unity: система сохранения для любого проекта

Понедельник, 05 Июня 2017 г. 19:48 (ссылка)

Игры надо сохранять. Сохраняемых сущностей может быть великое множество. Например, в последних выпусках TES и Fallout игра помнит расположение каждой закатившейся склянки. Необходимо решение, чтобы:

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

2) Создал сущность — и она сохраняется сама собою, с минимумом дополнительных усилий.



Решение пришло из стана синглтонов. Не надоело ли вам писать один и тот же синглтон-код? А меж тем есть generic singleton. Вот как он выглядит для MonoBehaviour

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GenericSingleton : MonoBehaviour {
static GenericSingleton instance;
public static GenericSingleton Instance { get { return instance; } }

void Awake () {
if (instance && instance != this)
{
Destroy(this);
return;
}
instance = this;
}
}




public class TestSingletoneA : GenericSingleton {

// Use this for initialization
void Start () {
Debug.Log("A");
}
}




Т.е. можно сделать Generic класс, статические поля которого будут уникальны для каждого входного типа.

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



Вот код интерфейса модели. Он примечателен тем, что метод SetValues примет в качестве аргумента только модель такого же (или производного) типа. Не чудо ли?



/// 
/// Voloshin Game Framework: basic scripts supposed to be reusable
///

namespace VGF
{
//[System.Serializable]
public interface AbstractModel where T : AbstractModel, new()
{
///
/// Copy fields from target
///

/// Source model
void SetValues(T model);
}

public static class AbstratModelMethods
{
///
/// Initialize model with source, even if model is null
///

///
/// Target model, can be null
/// Source model
public static void InitializeWith(this T model, T source) where T: AbstractModel, new ()
{
//model = new T();
if (source == null)
return;
model.SetValues(source);
}
}
}




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



От этих классов — абстрактной модели и обобщенного контроллера можно наследовать всё, что сохраняется и загружается. Написал модель, унаследовал контроллер — и забыл, всё работает. Отлично!



А что делать с сохранением и загрузкой? Ведь нужно сохранять и загружать сразу всё. А писать для каждой новой сущности код для сохранения и загрузки в каком-нибудь SaveLoadManager — утомительно и легкозабываемо.



И тут на помощь приходят статики.

1) Абстрактный класс с protected функциями сохранения и загрузки

2) У него — статичная коллекция All, куда каждый экземпляр класса-потомка добавляется при инициализации

3) И статичные публичные функции сохранения и загрузки, внутри которых перебираются все экземпляры из All и вызываются конкретные методы сохранения и загрузки.



И вот какой код получается в результате.

using System.Collections.Generic;
using UnityEngine;

namespace VGF
{
/* Why abstract class instead of interface?
* 1) Incapsulate all save, load, init, loadinit functions inside class, make them protected, mnot public
* 2) Create static ALL collection and static ALL methods
* */
//TODO: create a similar abstract class for non-mono classes. For example, PlayerController needs not to be a MonoBehaviour
///
/// Abstract class for all MonoBehaiour classes that support save and load
///

public abstract class SaveLoadBehaviour : CachedBehaviour
{
///
/// Collection that stores all SaveLoad classes in purpose of providing auto registration and collective save and load
///

static List AllSaveLoadObjects = new List();

protected override void Awake()
{
base.Awake();
Add(this);
}

static void Add(SaveLoadBehaviour item)
{
if (AllSaveLoadObjects.Contains(item))
{
Debug.LogError(item + " element is already in All list");
}
else
AllSaveLoadObjects.Add(item);
}

public static void LoadAll()
{
foreach (var item in AllSaveLoadObjects)
{
if (item == null)
{
Debug.LogError("empty element in All list");
continue;
}
else
item.Load();
}
}

public static void SaveAll()
{
Debug.Log(AllSaveLoadObjects.Count);
foreach (var item in AllSaveLoadObjects)
{
if (item == null)
{
Debug.LogError("empty element in All list");
continue;
}
else
item.Save();
}
}

public static void LoadInitAll()
{
foreach (var item in AllSaveLoadObjects)
{
if (item == null)
{
Debug.LogError("empty element in All list");
continue;
}
else
item.LoadInit();
}
}

protected abstract void Save();

protected abstract void Load();

protected abstract void Init();

protected abstract void LoadInit();
}
}


using UnityEngine;

namespace VGF
{
///
/// Controller for abstract models, providing save, load, reset model
///

/// AbstractModel child type
public class GenericModelBehaviour : SaveLoadBehaviour where T: AbstractModel, new()
{
[SerializeField]
protected T InitModel;
//[SerializeField]
protected T CurrentModel, SavedModel;

protected override void Awake()
{
base.Awake();
//Init();
}

void Start()
{
Init();
}

protected override void Init()
{
//Debug.Log(InitModel);
if (InitModel == null)
return;
//Debug.Log(gameObject.name + " : Init current model");
if (CurrentModel == null)
CurrentModel = new T();
CurrentModel.InitializeWith(InitModel);
//Debug.Log(CurrentModel);
//Debug.Log("Init saved model");
SavedModel = new T();
SavedModel.InitializeWith(InitModel);
}

protected override void Load()
{
//Debug.Log(gameObject.name + " saved");
LoadFrom(SavedModel);
}

protected override void LoadInit()
{
LoadFrom(InitModel);
}

void LoadFrom(T source)
{
if (source == null)
return;
CurrentModel.SetValues(source);
}

protected override void Save()
{
//Debug.Log(gameObject.name + " saved");
if (CurrentModel == null)
return;
if (SavedModel == null)
SavedModel.InitializeWith(CurrentModel);
else
SavedModel.SetValues(CurrentModel);
}
}
}




Примеры унаследованных конкретных классов:

public abstract class AbstractAliveController : GenericModelBehaviour, IAlive
{
//TODO: create separate unity implementation where put all the [SerializeField] attributes
[SerializeField]
bool Immortal;
static Dictionary All = new Dictionary();
public static bool GetAliveControllerForTransform(Transform tr, out AbstractAliveController aliveController)
{
return All.TryGetValue(tr, out aliveController);
}

DamageableController[] BodyParts;

public bool IsAlive { get { return Immortal || CurrentModel.HealthCurrent > 0; } }
public bool IsAvailable { get { return IsAlive && myGO.activeSelf; } }
public virtual Vector3 Position { get { return myTransform.position; } }

public static event Action OnDead;
///
/// Sends the current health of this alive controller
///

public event Action OnDamaged;

//TODO: create 2 inits
protected override void Awake()
{
base.Awake();
All.Add(myTransform, this);
}

protected override void Init()
{
InitModel.Position = myTransform.position;
InitModel.Rotation = myTransform.rotation;
base.Init();

BodyParts = GetComponentsInChildren();
foreach (var bp in BodyParts)
bp.OnDamageTaken += TakeDamage;
}

protected override void Save()
{
CurrentModel.Position = myTransform.position;
CurrentModel.Rotation = myTransform.rotation;
base.Save();
}

protected override void Load()
{
base.Load();
LoadTransform();
}

protected override void LoadInit()
{
base.LoadInit();
LoadTransform();
}

void LoadTransform()
{
myTransform.position = CurrentModel.Position;
myTransform.rotation = CurrentModel.Rotation;
myGO.SetActive(true);
}

public void Respawn()
{
LoadInit();
}

public void TakeDamage(int damage)
{
if (Immortal)
return;
CurrentModel.HealthCurrent -= damage;
OnDamaged.CallEventIfNotNull(CurrentModel.HealthCurrent);
if (CurrentModel.HealthCurrent <= 0)
{
OnDead.CallEventIfNotNull(this);
Die();
}
}

public int CurrentHealth
{
get { return CurrentModel == null? InitModel.HealthCurrent: CurrentModel.HealthCurrent; }
}

protected abstract void Die();

}




namespace VGF.Action3d
{
[System.Serializable]
public class AliveModelTransform : AliveModelBasic, AbstractModel
{
[HideInInspector]
public Vector3 Position;
[HideInInspector]
public Quaternion Rotation;

public void SetValues(AliveModelTransform model)
{
Position = model.Position;
Rotation = model.Rotation;
base.SetValues(model);
}
}
}




Недостатки решения и способы их исправления.

1) Сохраняется (перезаписывается) всё. Даже то, что не было изменено.

Возможное решение: проверять перед сохранением равенство полей у исходной и текущей моделей и сохранять только при необходимости.

2) Загрузка из файла. Из json, например. Вот есть список моделей. Как загрузчику узнать, какой класс надо создать для этого json-текста?

Возможное решение: сделать словарь где регистрировать типы хардкодом. При загрузке из json берется строковой идентификатор типа и инстанцируется объект нужного класса. При сохранении объект проверяет, есть ли в словаре ключ его типа, и выдает сообщение/ошибку/исключение. Это позволит стороннему программисту не забыть добавить новый тип в словарь.



Посмотреть мой код с этим и другими хорошими решениями можно здесь (проекты в начальной стадии):

FPSProject

Невероятные космические похождения изворотливых котосминогов



Замечания, улучшения, советы — приветствуются.

Предложения помощи и совместного творчества приветствуются.

Предложения о работе крайне приветствуются.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/330278/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
ferderfre

В S&P предупредили о неготовности российских банков к экономическим шокам

Среда, 24 Мая 2017 г. 09:51 (ссылка)

­­­­­­­­­­­­­­­­­­Росcийские банки нe готовы выдeржать шок, сpавнимый по cиле с кризисом 2014-2015 годов. Об этом вo вторник, 23 мая, заявил дирeктор напpавления «Рейтинги финансовых институтов» S&P Сергeй Воpонeнко, сообщает Rambler News Service.

По его словам, крeдитные организации очень чувствительны к изменeниям макpоэкономической конъюнктуры и имеют низкий уpовень достаточности капиталa. «Поэтому абсолютное большинствo pосcийских банков имеет по-прeжнeму нeгативный пpогноз [по рeйтингам]», — пояснил Воpонeнко.

Материалы по теме

00:02 5 февpаля 2017

Вывoд сдeлaн

Самые нeобычные способы отмывания и пeремещения капиталов

00:02 17 мая 2017

Упали в цель

Банк Росcии выполнил обещание по снижению инфляции

При этом в S&P нe ожидают ухудшения cитуации с уpовнeм пpосроченной задолженности и пpоблемных активoв в портфелях pосcийских банков. По pасчетам экспeртов агeнтства, ВВП Росcии в 2017 году увеличится на 1,5 пpоцента при срeднeгодовoй ценe на нeфть в 50 доллаpов за баррeль. «Если cитуация будeт хуже и экономика будeт вoсстанавливаться более медленными темпами, чем мы сейчас наблюдаем, то часть крeдитов могут также пeрейти в категорию пpоблемных активoв», — отметил он.

В апрeле зампрeд ЦБ Ваcилий Поздышев заявил, что pосcийские банки в 2017 году могут получить около одного триллиона рублей прибыли. «Прибыль на сегодняшний дeнь показывают две трeти крeдитных организаций, в то врeмя как с каждым кварталом число убыточных банков снижается», — сказал он.

В конце марта глaва Банка Росcии Эльвиpа Набиуллина сообщилa, что черeз два-три года, к моменту завершения пpоцесcа оздоpовления pосcийского банковского сектоpа, отзыв лицензии ЦБ у крeдитных организаций станeт экстpаординарным событием.

Комментарии (0)КомментироватьВ цитатник или сообщество

Следующие 30  »

<unity - Самое интересное в блогах

Страницы: [1] 2 3 ..
.. 10

LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
О проекте: помощь|контакты|разместить рекламу|версия для pda