пятница, 30 мая 2014 г.

Как работать с людьми страдающими виктимным поведением


Почему я съедаю те охотничьи колбаски или виктимное поведение как путь к ничтожному существованию.
 

 Что бы было понятней что такое виктимное поведение

 

Признайтесь себе, вы латентный мазохист. Бывали случаи, когда вы сами вставали в позицию жертвы и наслаждались этим? Самый глупый способ реализации в этой жизни - это отказ от N без объективных на то причин. "Я не буду жрать конфеты потому что.... ну я их не ем, посмотрите, я не ем конфеты". Социальные изгои, которые банально не реализованы в своей жизни, бессознательно создают выдуманные проблемы в которых они признают себе виноватыми и наслаждаются этим! Мазохизм в чистом виде. Благо я могу вспомнить всего 2-3 человека из своего окружения которые промышляют таким, у них есть одна общая черта: когда пред ними человек со стальными яйцами, они теряются, когда они теряются им можно впарить вообще что угодно.

Ну бывает


Занимаясь столь невинным самоудовлетворением, человек становится уязвим, он впитывает как губка, его критическое мышление превращается в извращённую фикцию. Вы когда-нибудь замечали какая у них тяга к последовательности? А знаете, что из этого можно вынести? Можно получить неплохого раба, правда работник никудышный, но зато не прихотливый.

Его модель поведения помогает ему заниматься самой отстойной работой и его стимул будет зиждется на столпах которые он сам себе придумает. Он считает себя работягой каких не видел свет, на нём большая ответственность, у него много дел, он страдает под гнётом обязательств! Вы уже чувствуете? Он не бросит заниматься тем дерьмом которым вы его нагружаете, он будет страдать и наслаждаться. Чуть ранее я упомянул, что раб хороший, но не работник, почему? Да потому что он удовлетворяет себя, тратит время на всё, но не на работу, много разговоров о сложности работы, но нет работы.  Нужно много терпения и контроля, я, завидев в своей команде подобного человека, стараюсь как можно скорей с ним расстаться. Но мы живём не в идеальном мире и иногда приходится работать с разными личностями, поэтому дам пару советов как с ними работать:
  •  Корень проблемы в том, что этот человек возможно в прошлом был социальным изгоем, возможно в школе, без поддержки со стороны он избрал на себя такую роль и это хорошо укоренилось в его сознание. Как обрадовать нищего? Кинуть ему монетку. Здесь также, дайте ему другую социальную роль, используя слова которые не доводилось ему слышать ранее: “Привет, тут без тебя не обойтись, сможешь сделать N?”, “Ну что, труженик коллектива, как дела с N?”. Введите его в социум, не ощущая себя не признанным ему не будет надобности жаловаться.
  •   Старайтесь не давать ему переложить ответственность на себя, это они любят делать, выдумывая про себя героические образы: “Я виноват в том, что мы не успели вовремя сделать N… (балаболия про то как же он раскаивается и какой он плохой)”. В таких случаях лучше сразу переходить в контр наступление беря на вооружение механизм последовательности: «И что мы будем делать?”, если видите, что он не подготовлен к такому вопросу лучше сразу гоните в шею, проблем меньше будет, а вот если он действительно думал над этим, а не только мечтал, как же его поимеют, то с этим человек стоит работать. Правда я отошёл не много от темы, суть в том, чтобы не подыгрывать его страдальческому лейтмотиву. Причём здесь механизм последовательности? Нам нужно увидеть последовательности этого человека для принятия решение стоит ли работать далее.

Заключение


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

Причём здесь охотничье колбаски? Я люблю людей которые могут со спокойной душой заточить колбаски с литром пива, и презираю которые ”дрочат” на свой отказ от мучного.

вторник, 6 мая 2014 г.

Popup окна, плагин для WordPress

Для увлечения конверсии трафика, многие могут попробовать использовать Popup окна на своих сайтах. Вот и я решил прибегнуть к этому способу, для реализации своих планов я воспользовался плагином WordPress PopUp

Скачать плагин

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

В левом меню будет вкладка Pop Overs, нужно навести на неё мышкой и выбрать в всплывающем меню Create New.


По порядку:
  1. Имя окна
  2. Содержимое окна
  3. Условия при которых будет показываться окно, очень гибко. 
  4. Сюда перетаскивать условия
  5. Поставив галочку,  мы скажем чтобы окно центрировалось и масштабировалось самостоятельно. То есть было строго по центру.

Ниже ещё есть опции. Допустим чекбокс Remove the "Never see this message again" link отвечает за показ кнопки скрытия сообщения на всегда, советую её не ставить, у пользователя должна быть возможность навсегда избавиться от окна.

Ещё есть опция Pop over appearance delays, там можно указать когда будет появляться окно, по стандарту там стоит сразу. Для своих окон я предпочёл вариант с задержкой в 5  секунд.

Создав новое окно, его предложат сразу активировать, соглашаемся. Далее нужно найти Settings во вкладке Pop Overs. Там есть опция Pop Over loaded using, если у вас не отображается окно стоит изменить её на Page Footer. У меня допустим не отображалось именно из-за этого :)

Локализация 

У этого плагина есть одна не приятная черта, кнопка "Never see this message again" на английском :)
Но это поправимо, в файле wp-content/plugins/wordpress-popup/popoverincludes/css/fixed/popover.php на 8 строке можно её поменять.

четверг, 10 апреля 2014 г.

Массовая покупка трафика, что к чему


Уделив 2 дня и небольшой бюджет, вопросу трафика я получил некий опыт которым хочу сейчас поделится. 

Что такое массовый трафик? К массовому трафику я отношу "сырой" трафик который идёт большими кучами, с площадок других людей и который приводит тела у которых траст к вам нулевой. Такой трафик холодный и чтобы была хорошая конверсия нужно много усилий. Вы вообще никто и звать вас никак, большая часть народу разбежится на этапе загрузки так и не поняв что вы хотите. Не говоря уже о совершение некого действия.

Задумывались ли вы когда-нибудь о том чем отличаются уникальные посетители? И почему 5000 уникальных посетителей иногда хуже чем 100? Есть много источников хорошего трафик есть много источников просто трафика а есть ещё больше источников пустого трафика. Но нету абсолютно ничего идеального, здесь как при добыче золота, трафик оценивается средним количеством ценного металла на кубометр земли.  И даже если вы купите приск, есть большой шанс того что в итоге либо банально Вы не сможете добыть средний показатель золота из земли либо в связи с рядом событий земля оказалась отвратительного качества.

Пока-что я могу вспомнить о следующих источниках:
  •  Попандеры\Попкликеры - Самый жёсткий и сырой трафик, конверсия либо отсутствует как таковая либо ничтожно мала. В самых лучших условиях мне удалось получиться конверсию 10 установок на 1000 посетителей. Попандер и Попкликер это всеми не любимые всплывающие окна либо при закрытие рекламного объявления или клике по странице. Самые низерные цены это 14 рублей за 1000 человек. Но в зависимости от таргетирования и прочего цены поднимаются в среднем до 70 рублей за 1000 тел.
  • Баннерная реклама - Тут дела обстоят намного лучше, но и такой трафик стоит дороже. Тут главное видеть грань. Если я куплю на каком-нибудь торрент трекере или ещё лучше вообще в какой-нибудь рекламной сети баннерную рекламу своего фильтра рекламы - то это я называю массовым трафиком. А вот если я куплю баннер на каком-нибудь узкоспециализированном форуме который рекламирует мои курсы, это уже не массовый трафик.  Цены в среднем 400 рублей за 1000 переходов, но и конверсия больше. Сам массово баннера не закупал, но в будущем планирую этим заняться.
  • Покупка прогона по базе - Здесь как и с баннерами, ребята которые к вам придут будут уже подготовлены и даже более знать зачем они сюда вообще зашли. Конверсия больше но и цены соответственно. Но есть и проблема, платите за прогон. Так-что кто знает сколько вообще из письма придёт? 
  • Заказ постов в группах (социальные сети) - Это моё любимое но и в итоге мы получаем почти комбинирование пред идущих способов, а именно: 
    • Вас не любят. 
    • Пользователь знает куда идёт и зачем 
    • Платите за пост, по этому никто ничего не гарантирует  

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

Для первых двух случаев я использовал PopUnder - вполне приемлемая биржа, очень понравилось что новые компании рассматривают в течение 10 минут. За два дня я взял от туда ~40 тысяч уникальных посетителей и провёл эксперименты с разными лендингами. Самый дорогой и плохо конвертируемые трафик был из США и ЕС. Допустим на англоязычный лендинг с вполне приемлемой игрой я запустил 10к человек из США. Итог? Ноль загрузок. Запустил 6000 человек из СНГ. Итог? 28 загрузок и 20 установок. Самый хороший результат показал попандер с лендингом фильтра рекламы, конверсия 1%. 

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

воскресенье, 23 марта 2014 г.

Необходимые плагины для WordPress

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

Akismet - Пожалуй лучший антиспам плагин для WordPress. Имеет бесплатную версию, очень гибок в настройки и почти никогда не пропускает спам! Кстати совсем недавно количество заблокированных комментариев в общем числе превысило 50 миллиардов!

All In One SEO Pack - Полный пакет всего что только нужно по части SEO для WordPress. Бесплатный, функциональный, в общем всё что нужно!

Google XML Sitemaps
- Генерирует карту сайта которая помогает поисковым системам лучше сканировать ваш сайт, абсолютно не заменимая штука (кстати есть альтернатива которая идёт вместе с WP но я ей не пользовался). Так-же плагин полностью бесплатный.

Shortcodes Ultimate - Шорткоды это дар богов! Нет серьёзно, это очень удобная штука! А благодаря данному плагину у вас появляется воистину богатый набор этих самых кодов, так ещё и визуальный интерфейс для их использования в добавок. Полностью бесплатный.

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

Acunetix WP Security
- Какой бы хорошей CMS не был WordPress он всё же уязвим. Этот плагин позволяет повысить безопасность вашего проекта, достаточно лёгок в обращение, но новичку может показаться слишком сложным.

Вот мой список плагинов :)
Если у вас тоже есть что-то что вы стараетесь брать с собой, пишите в комментариях!

понедельник, 17 февраля 2014 г.

Как я ASP.Net с JustClick подружил.

 Введение

Что такое JustClick?

"херня забагованая" (с) тим-лид
JustClick - Это такая платформа для инфобизнесменов,  соль в том что там всё автоматизировано, повсюду цветастые кнопки на которых написано "сделать красиво".

Но к сожалению не всё так радужно. И вот мы - кучка программистов уже делаем свою SaaS, с шахматами и балеринами, но для начало нам нужно было плавно переводить все ресурсы. После того как была написана основа мы приступили к интеграции, а именно к покупки товаров. Соль в том что бы при покупки в JustClick, товар был бы доступен и в личном кабинете на нашей платформе, собственно кусок из моих похождений я постараюсь описать в данной записи.

Это не мы такие, это реквест такой

Мне очень понравилось что в JustClick было API и мне очень не понравилось какое у них API. Самый логичное решение сделать обмен через скажем JSON или хотя бы XML. Но нет, ребята решили что PHP у всех и нужно пользоваться чем-то сильно зависимым от подобных языков.

Но нам ли жаловаться. 

Для начала нужно проделать такой финт конём (сразу скажу что с Asp.Net слабо знаком так-что быдлокодер костылём велосипед подгоняет) 
-Берём и копируем отседова секретный ключ подписи "Мой магазин" - "Магазин" - "Настройки" - "RussianPostService и API" 
-Создаём новую веб форму.
-Идём в товар, ставим в настройках API в графе оповещения ссылку на нашу форму.
-В форме ловим пост запрос который выглядит так в PHP и отправляется через urlencode(!):
 
array(
'id' => номер заказа
'first_name' => имя клиента
'last_name' => фамилия клиента
'middle_name' => отчество клиента
'email' => мейл клиента
'phone' => телефон клиента
'city' => город доставки
'country' => страна доставки
'address' => адрес доставки
'region' => регион доставки
'postalcode' => почтовый индекс
'created' => время создания заказа
'paid' => время оплаты заказа
'items' => array( массив товаров
array(
'id' => символьный идентификатор
'title' => название товара
'sum' => стоимость товара
),
array(
'id' => символьный идентификатор
'title' => название товара
'sum' => стоимость товара
),
...
)
'hash' => md5(номер заказа + мейл клиента + дата оплаты + секретный ключ)
)

 
До нас доходит примерно следующее

 id=3224966&first_name=asf&
last_name=&middle_name=&email=*******&phone=&city=&country=RUS&address=sdf&region=&postalcode=&created=1392641297&paid=1392641312&items[0][id]=ebook&items[0][title]=??????????? ?????&items[0][sum]=500.00&items[1][id]=0&hash=*********&


ASP.net своими силами пытается разбросать это всё по коллекции типа NameValueCollection
и скажу даже больше, у него это получается! Ну как получается....
Допустим мы можем взять из Request все не вложенные элементы.

 
 
Requeste["id"]; //norm
Requeste["email"]; //norm
Requeste["items"]; //EMPTY!!!

А фишка в том, что все вложенные элементы не парсятся до ещё одного набор коллекций. Нет. Оно превращается в ключи... Выгляди это примерно так:

 
Requeste["items[0][sum"]; //norm
Requeste["items[2][sum"]; //norm

Работать как все понимают с этим трудно, и даже слегка больно.

Заключение

Все пидорасы один я дартаньян (c)

Либо я не секу фишку, либо ребятам из JustClick стоило сделать лучше. Но в любом случае надеюсь эта заметка кому нибудь пригодится. 

пятница, 24 января 2014 г.

VisualWebSiteOptimizer баг с вариантами.

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

Thank you for contacting us. I have checked the test and would like to tell you that there is an iframe element when the webpage is loaded in the VWO editor which is causing the CSS selector path to be different when the visitor lands on the webpage directly and hence VWO is not able to find the element and apply the changes (please check the screenshot 1 attached). 

So I would recommend that you either insert an ID on the DIV element after the opening body tag so that the CSS selector path is calculated from that element or you can create an MVT test and add the CSS selector path (font.actiontitle>center) manually (as shown in the screenshot2) and then disable all the variations except for the control and the last variation in the test.
  Я как нормальный человек понял мало. Но взглянул на лэндинг которые сверстали фрилансеры, я впал в не большую фрустрацию с большим желанием выпить ещё одну чашку кофе. Дело в том, что на КАЖДЫЙ тег приходился свой собственный id, самое забавное что это не генерированная странница а свёрстанная вполне реальным человеком с вполне функциональными руками (ну по крайней мере в ухе ими поковыряться можно). Из-за такой "пёрстости" страницы, ломались селекторы. Проблема решалась заклчением всей страницы в див с id = VWOWrapper, под всей страницей я имею ввиду конечно-же всё от ‹ body › и до ‹ /body › .
Надеюсь Вам это помогло!

Кастомизация Unity Web Player [Preloader]


четверг, 9 января 2014 г.

Хостинг Unity Web Player

Написал основу за выходные, сейчас тружусь над улучшением сервиса :) 

Хостинг Unity Web Player

Пишем Dissolve Shader [Хабра]

Введение

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

  Путей реализации есть несколько:
  • Alpha
  • CutOff
  • Grab Texture
В итоге у нас получится 3 шейдера, 2 использующие только альфу и которые могут взлететь на моб. девайсах и один с AlphaTest который выглядит посимпатичней но более прожорливый. Благодаря AlphaTest мы можем отключить отсечение невидимых полигонов и не получать наслоение. Но заплатить придётся шейдерной моделью 2.0 и использовать 3.0 из-за чего нельзя будет использовать на моб. девайсах.

Каркас

Общий алгоритм примерно такой:
  • Берём яркость пикселя с маски разрушения или прямо с главной текстуры
  • Сравниваем эту яркость с N
  • Если яркость больше N то альфу пикселя ставим в нолик
В итоге получится не так красиво как на первом видео.
Нам не хватает карт нормалей, и самого крутого. Линий! Алгоритм инлайнов у меня такой:
  • Берём яркость пикселя с маски разрушения, но с оффсетом по UV + LineSize. И ещё один но оффсет уже UV - LineSize
  • Если хотя бы один из пикселей меньше N, то мы устанавливаем цвет пикселя из текстуры для линий
  • Иначе ставим альфу в ноль (Это как замена аналогичной операции в первом алгоритме)
Резюмирую выше сказанное, мы получаем отсечение по маске и если пиксели отсекаем то проверяем нету ли впритык к нему не отсечённые, если они есть мы становимся краем и ставим себе определённый цвет.

Ближе к телу коду

Если прибавить ко всему выше сказанному наложение нормалек и смещение текстуры линии ещё по синусоидальному времени, получится вот такое вот полотно.
 Shader "HolyMonkey/Dissolve/Bumped" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
  _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
 }
 
 SubShader {
  Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
  LOD 300
  ZWrite On
  Cull Off
  CGPROGRAM 
  #pragma target 3.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert alphatest:_Cutoff
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
                        float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
          half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
          half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
    
          o.Albedo = c *  _MainColor;
          o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
          o.Alpha = 1;
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
                  o.Alpha = 0.0;
               }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}
Ещё можно поиграться с не которыми аспектами и получить следующее
Shader "HolyMonkey/Dissolve/Culling-Mobile" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
 }
 
 SubShader {
  Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
  LOD 300
  CGPROGRAM 
  #pragma target 2.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert alpha 
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
            float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
      half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
      half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
    
      o.Albedo = c *  _MainColor;
      o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
      o.Alpha = 1;
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
                  o.Alpha = 0.0;
               }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}
Shader "HolyMonkey/Dissolve/NotTransparent" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _BackTexture ("Back Texture", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
 }
 
 SubShader {
  LOD 300
  ZWrite On
  Cull Off
  
  CGPROGRAM 
  #pragma target 2.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  sampler2D _BackTexture;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
            float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
      half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
      half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
   half4 bc  = tex2D(_BackTexture, IN.uv_MainTex);
      o.Albedo = c *  _MainColor;
      o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
         o.Albedo = bc;
         o.Normal = float3(1,1,1);
      }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}

Заключение

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