Показаны сообщения с ярлыком development. Показать все сообщения
Показаны сообщения с ярлыком development. Показать все сообщения

понедельник, 9 декабря 2013 г.

5 things you need to implement in any mobile game

русская версия - здесь

I have three posts in drafts(called "You don't need server" and "3 reasons to switch from Asset Server", "Execute impossible to pardon: how to deal with hackers"), but decided to write this one just because it seems more timely than others.

We had discussion with Yuri about what makes any game perfect and what features must be implemented and come up with some common and must-have features:

  • in-app-purchases. No comments here. If you want to make money from your game, you'd better have well-tested, stable in-apps;
  • analytics. The thing is you can not predict user behaviour unless you have any clue what your user is doing in the game. And it's better to have as much information as possible - you know where is your problem in your game mechanics and can easily fix it up;
  • local and remote push notifications. We didn't implement them in the first releases of Road Smash and we feel regret about it. What is the easiest way to let the users play updated game? Obviously, push notifications.I know that users may hate pushes and remove your app just because they are got annoyed by your app, but in 70% it works.
  • Anticheat protection. You know, cheaters always exist, especially on android and you need to prevent your game from being hacked. Somebody may say that you need to protect everything, somebody have an opinion that you need to give up on hackers and let them play. I think that hackers wouldn't pay. They would keep hacking the game until they find something or even delete it from their devices, but they would never pay. So I came up with the decision here: protect only that things that cost money or may affect other users. In business terms there are two most important things for developer: users that bring money. When I say money, I mean in-apps, when I say affect other users, I mean scoreboard, social, competition parts of your game. And you need to keep tiny balance between letting gamers play comfortably and prevent players from stealing your money.
  • Ads. I underestimated role of ads, thought it's annoying and may push your user away. But I was wrong. Firstly, you can integrate ads, so they will become part of your gameplay. Users will want to see some ads just to get some goods instead. And of course, it is a great chance to  get money from users that will never pay :)
The main purpose of any game is to have a lot of users in game and keep them as long as long as possible, letting them pay for any reason. In that meaning these five features described must be implemented, well-tested as soon as possible.

And to make this post more concrete, I have some links to assets to share with you to get that features implemented in the easiest way.
  • in-apps: use unibill. It supports app store, google play, windows store out-of-box, including receipts, subscriptions, etc. Must-have!
  • analytics: there's a wonderful and free plugin, called GameAnalytics. It supports events, heat maps, gameplay stats. If you are fan of old-school analytics, you may check out for my wrapper to Flurry plugin in my github repository, I'll push all the code as soon as I find free time for it. 
  • push notification: there are too many good plugins in assets, so I don't know what's the best option here. I'd recommend pushwoosh service, because it provides a lot of features out-of-box, but let me leave this topic open.
  • anticheat: well... there's no common solution as it really depends on what kind of game you are working on. Maybe some kind of playerprefs encryption, in-apps encryption? Did I miss something?
  • ads: there is a bunch of different options: admob, tapjoy, adcolony, applifier. Some of them provide banner and image ads, some of them kind of video or partnership ads. Choose one you like the most.

пятница, 21 июня 2013 г.

пятница, 24 мая 2013 г.

Так, ни о чем

один файл, а внутри: два энама, три класса, две руками написанные стейт-машины, 400 строк кода. Здравствуй, быдлокод:


среда, 17 апреля 2013 г.

Dynamic texts in ngui

The only problem I have to deal with 2D UI in NGUI plugin is text fonts. In details, there's a bunch of problems:

  • Dynamic font support (UPD: from NGUI 2.5 dynamic fonts are supported out-of-box)
  • Localization(arabic, hebrew languages, chinese etc).
  • Input texts
As I'm working on localization in deep, I found some useful things to solve problems described above:
  • for dynamic font, use https://github.com/imkira/unity-sysfont. It seems to be out-of-date (it hasn't been updated for 9 months), but it works and you need just to tweak it for youself. Maybe I'll finish it in holidays.
  • for chinese, japanese dynamic fonts works ok, use plugin above. If you intent to support arabic languages,  use http://u3d.as/content/abdullah-konash/unity-arabic-support/2B8. This asset allows you to write in rtl mode. Now I'm looking for hebrew plugin, or if I find someone who can read hebrew, I'll write it for myself. 
  • Situation about input text is troublesome. Changing uiinput component will cause problems with supporting and I don't like to do it. But there's no other way to cope with it.

пятница, 5 апреля 2013 г.

//TODO, //HACK, FIXME

В мире спортивного программирования всегда все просто: у тебя всегда валидные данные, обо всем позаботились организаторы. В промышленных масштабах это далеко не так: по закону Мерфи если что-то может пойти не так, так обязательно и будет. Поэтому ты тупо пишешь кучу проверок на случай ядерной войны. Или не пишешь. Оставляешь //TODO: check c надеждой на то, что когда будет скучно и не захочется ничего делать, будешь писать эти глупые проверки.

Сегодня запустили игру, она падает на уровне. Смотрим, где падает: null-reference exception. Смотрим код:
public void DoAction(Transform t) {
 //todo check before setting
 t.localPosition = foo;
 t.localRotation = bar;
 t.localScale = foobar;
}

Падало как раз при присвоении, потому что t - null. Как говорится, без комментариев. Хотя есть один: "//TODO:" существует не для того, что его оставляли и забывали, а для того, чтобы это фиксили и делали это как можно быстрее. И для //HACK, //FIXME инженерный закон "работает - не трогай" не катит - это просто бомба замедленного действия, который когда-нибудь рванет в совсем неожиданное время и неожиданном месте(ну, к примеру, во время презентации или, не дай Бог, релиза).

воскресенье, 24 марта 2013 г.

Hack day?

У меня нет никаких идей, чем можно позаниматься в следующие выходные. И я давно ничего не писал в гаражном стиле - сесть и быстренько накатать. Корочеееее, идея: на следующих выходных устроить себе нечто наподобие hack day. То есть к пятнице нужно придумать идею, а к вечеру воскресения уже реализовать прототип. Чего-нибудь простого, интересного, но уже работающего. Если будет запор идей и ничего в голову не придет, то буду разбирать старые завалы, начну переписывать халял гайд.

Если вдруг у кого-нибудь есть идеи (в приоритете мобайл-дев, ios/android), напишите мне пожалуйста. Даже самая глупая идея имеет смысл. А вдруг кто тоже хочет поучаствовать - то тем более :)


суббота, 23 марта 2013 г.

Эффект молнии в Unity3d

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

  • это должна быть ломаная линия без самопересечений;
  • у нее должны быть параметрами выделены начало и конец;
  • можно задавать скорость молнии;
  • можно задавать амплитуду - насколько сильно молния уходит от "прямого" маршрута;
  • можно задавать визуальные характеристики молнии: цвет, толщина линии и так далее
  • да, и чтоб ее можно было "запаузить", то есть сделать так, чтобы след от молнии остался на экране указанное мною время.

Вот примерно это у меня в конце и получилось: 


Как решить этот вопрос?

Нулевая мысль: надо загуглить. 

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

Устал искать, решил взять заготовку и написать сам.

Первая мысль: использовать партиклы. 

Как? Непонятно. У кого есть идеи, велком.

Вторая мысль: шейдером.

Сделать в любом редакторе 3d прямую, а потом создавать ее, применив фрагментный шейдер, который будет:
  • отрисовывать ее не сразу, а по какому-то времени. Таким образом, мы добьемся эффекта, что молния "бьет", можно управлять скоростью.
  • рисовала не прямую, а ломаную в заданной амплитуде. По сути, это просто: амплитуда - это просто абсолютное значение координаты относительно Y, нужно делать кривое зеркало в 1D пространстве.
  • ну и цвет - простое умножение на цвет. 
К слову сказать, первое место из той ссылки как раз и юзает такой шейдер, но меня он отпугнул своей неуклюжестью и тяжелой отрисовкой. 

Уже решение: взять и тупо рисовать.

И на мой взгляд, самое простое и гениальное решение: можно провести какой-нибудь "безбашенный" шатающийся отрезок из точки А в точку B, а в позициях, где он побывал, нарисовать пиксели.
Более того, в Unity уже есть так называемый trail renderer, в нем есть и толщина линии, и материал с нужным мне цветом. По названию понятно, что это штука, которая рисует на позиции, где побывал гейм-объект. Юнитеки будто знали :) То есть вся задача заключалась в том, чтобы создать пустой трансформ в точке А и довести ее до точки В, в update иногда сбивая ей маршрут.

Код слишком простой, поэтому выкладывать его нет смысла. Ну а поиграться можно выше или вот здесь:




понедельник, 18 марта 2013 г.

Разговаривать на общем языке

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

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

Теперь у меня новая проблема: мне надо объяснить моим коллегам, что когда нужна какая-либо функциональность, не нужно страдать синдромом not invented here, нужно взять готовую либу и, если нужно, добавить недостающую функциональность. И, блин, не унаследовав от базового класа, а используя композицию!

Когда я вижу простыню из 900 строк, у меня возникает желание сделать вот так:


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

 и обязательно ищу в нем баг, чтобы получилось вот так:


Вы не поверите, в 90% я его нахожу :)



Честно, не надо придумывать заново колесо, не надо проявлять фантазию в именах переменных, пользуемся готовыми паттернами, реюзаем код. Проще говоря, для себя вывел следующие правила:
  • Используем единый стиль форматирования, желательно тот же самый, что используется внутри общества, в котором вы живете. Потому что если вы пишете иначе, то вам сложно понять код других программеров, а другие будут плеваться на ваш код. Это все равно как русскому туристу в Китае на рынке договориться о скидке.
  • Самое сложное - придумывать названия (переменным, классам). Это правда. Вот не ленимся переименовать кнопку c ButtonX на MessageButtonBehaviour, anotherTemp на что-либо более подходящее. Я уж молчу о переменных типа ttt, secondVar, var5 (я не шучу - сегодня видел в боевом проекте).
  •  Юзаем паттерны, а не изобретаем их! И не надо делегат называть адаптером(привет андроид!), не надо хвалиться, что придумал новое супер решение, не прочитав шестую страницу банды четырех. 
  • Не забываем, что паттерны паттернами, но принципы KISS и YAGNI игнорировать нельзя. Вообще, сначала применяем здравый смысл, а потом бегите за стереотипным решением.
  •  Изучаем алгоритмы и структуры данных не для того, чтоб победить на топкодере и получить новую футболку, а чтоб знать внутренности структуры данных и алгоритмов, уметь применять на практике и если нужно, написать самому. 
  • И да, если знаем алгоритм или структуру, то применяем готовое решение, а не пишем собственный мегабыстрый класс! Сегодня рыдал от строчки типа такого: public List<string> itemsStack = new List<string>();. Угадайте, что это за структура данных? Угадайте, как автор этого шедевра делал push, pop, top? И это было в файле объемом 900 строк!!!!!1111 Я рискнул рефакторить, но позже понял, что это было плохой идеей, потому что этот гребанный стек применялся еще где-то и передавался ref-ом в какой-то левый класс, который зачем-то использовал его по-своему как список(linkedList)!
  • И да, не боимся пользоваться плагинами, не ходим грудью колесом аля "я все умею!", все самое лучшее уже давно написано за нас. Мы жмотимся на плагин стоимостью 100 баксов, но сами в течение пяти дней готовы допиливать собственный говнокод, почти выполняющий функции того плагина.
  • Не забываем развиваться, изучать новые фичи своего инструмента. Поверьте, вопреки распространенному мнению, обновление - это фикс багов и добавление новых фичей, а не наоборот! И если в языке X появилась штука, которая позволяет в одну строчку написать то, что вы писали в сорок - то даже дурачок Боб, не сумеющий написать свое имя наоборот(с), поймет, что надо юзать эту штуку!
Я очень рад, что в лкш ввели ручную проверку кода. Прикиньте, сколько бы еще можно было родить алгоритмических монстров, способных написать соптимизированную регекспу, но не способных разобраться в лапше из кучи классов. Надеюсь, они вряд ли столкнутся с теми проблемами, c которыми сталкиваюсь я.

P.S. На проекте у нас два программиста: коллега и я. Сегодня произошел священный спор по поводу египетских скобок. Я сторонник египетских скобок, аргументировал так:

  • меньше ненужного пространства при той же читабельности
  • большинство проектов (включая исходные коды юнитеков), написано с применением данного стиля, то есть он стандарт де-факто.
Он аргументировал это так:
  • египетские кнопки это плохо
  • я привык писать по bsd стилю, по-другому не умею.
  • весь мир неправ.
В общем, это был священный спор и каждый остался при своем мнении. Вдруг кто считает иначе, велкам :)








воскресенье, 10 марта 2013 г.

Пользователь! Ты скотина!

Не, я серьезно! Пользователь, пользующийся АБСОЛЮТНО БЕСПЛАТНЫМ приложением и возникающий по поводу того, что что-то работает не так, как он хочет - ты последняя пользовательская СКОТИНА!

Как пример: Вот поищите в app store  приложение Ted - ну просто отличнейшее приложение для просмотра огромного количества видеолекций на самые разные темы, смотри -не хочу. Лучше приложения я вообще не видел. И маркетологи решили выпустить его на российском рынке.

Маркетологи, вы ошиблись! Если по всему миру у вас только положительные отзывы и пять звезд, то российский рейтинг еле дотягивает до трех звезд с типичными комментариями: нет русского языка! Я не верю, что доходов от наших нищебродов много, а рейтинг и хорошее имя от этого портится :(

А теперь к тебе, пользователь! Запомни несколько моментов:

  • Разработчики тебе ничем не обязаны, тем более если ты пользуешься полностью бесплатным приложением! И вообще нет разницы, это айфон пятый или андроид за 3000 рублей. Не устраивает - проходи мимо. 
  • Да, если у тебя слабый телефон - не жалуйся, что приложение тормозит или вообще не поддерживается у тебя; ты сам выбрал категорию hard life, когда покупал девайс. 
  • Если у тебя есть конструктивная критика - обратись к разработчикам (по мылу, сайту) и предложи, как можно сделать лучше. Поверь, разработчики ценят это и прислушиваются  к новым идеям! Даже врачу жалуются не просто так - он может предложить решение вашей болезни. 
  • Если ты рассказал свои идеи - не надейся, что завтра же твои хотелки будут реализованы - во-первых, программист тебе не обязан, а во-вторых, возможно, это трудно реализуемо или вообще отложено на другой срок. 
Вообще считаю, что пользователя, который поставил одну звезду приложению, нужно кастрировать. Вот сидишь в свободное время, делаешь не игру какую-нибудь, а реально полезные тулзы, чтобы жизнь стала хоть немного лучше, а тебе приходит фидбек, что ты все делаешь зря, мне синенький цвет не нравится и вообще ничего не работает(при этом совершенно не понятно, что же там за проблема). В такие моменты руки опускаются - хотел только помочь, а получилось наоборот. Да ну нафиг, сделаю лучше под заказ еще один angry birds - и приятнее, и деньги платят. 

суббота, 30 июня 2012 г.

U do not need scrum

Well, I tried scrum. Honestly. It's a pretty good development method and very effective. If everything goes right, it may rapidly increase yr and teammates development speed. Everyone knows his tasks and may predict time to complete them. If something changes, there will be time to easily change direction of development and fix everything up.
Unfortunately, scrum has its own boundary of applications. In imaginary ideal world, where everything is predicted and anything u want to do u do from first attempt it is an ideal solution. But we live in other reality where above mean sea level may be positive and negative values, where sin or cosine values can be any value and there's no prohibition of taking square roots from negative numbers. And there's no place for creativity.

So, it's just words. Why do u need scrum? U need scrum:

  • when u have detailed, self-explanatory concept document
  • when u know exactly yr tasks
  • when u can estimate yr tasks
  • when u have an image of app in yr head  and may guess how it would work
  • when u need to quickly get results
  • when u need to see changelog of the app
But u do not scrum:
  • if there's no agreement with teammates about design and functionality
  • if u can not estimate yr tasks, because it's a creativity process depending on inspiration
  • and u can make over one task again and again
  • if u need to create something new, conceptional
Now I have six tasks on my board and can estimate three of them. Others are connected with design and may be overdone many times. So, if u ask me when I'm gonna finish my work and release next version, I won't give u any estimates or predictions. Even if I do, that will be not truth.