danilaxxl danilaxxl

CollectableItemData.cs

[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]

GoloGames GoloGames

vadya_ivan, рад, что вам игра показалась интересной : )

P.S. Кстати уже доступна бесплатная демо-версия в Steam

vadya_ivan vadya_ivan

Визуал, задумка, музыка , механики, все в цель

GoloGames GoloGames

Ato_Ome, спасибо за позитивные эмоции, будем стараться : )

Ato_Ome Ato_Ome

Потрясающий результат, все так четенько, плавненько)
То ли саунд, то ли плавность напомнили мне игрушку World of Goo, удачи вам в разработке и сил побольше дойти до релиза!)

Cute Fox Cute Fox

Graphics are a little cool, good HD content. But this game doesn't cause nary interest me.
However the game is well done.

GMSD3D GMSD3D

Почему действие после всех условий выполняется?
[step another object]

Zemlaynin Zemlaynin

Jusper, Везде, но наугад строить смысла нет. Нужно разведать сперва территорию на наличие ресурсов.

Jusper Jusper

Zemlaynin, а карьеры можно будет везде запихать?
Или под них "особые" зоны будут?

Zemlaynin Zemlaynin

Это так скажем тестовое строительство, а так да у города будет зона влияния которую нужно будет расширять.

Jusper Jusper

А ссылка есть?

Jusper Jusper

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

split97 split97

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

split97 split97

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

ViktorJaguar ViktorJaguar

Почему я нигде не могу найти нормальный туториал, где покажут как экипировать предмет (например, меч) в определенную (выделенную под оружие) ячейку???

Логотип проекта Unity

#3 Vertex and Fragment Shader

Vertex and Fragment Shader

В этой статье мы напишем простой вертексно-пиксельный шейдер, который
будет натягивать текстуру(логотип XGM) на объект(в моем случае на
сферу).
Итак, приступим.
Для начала создадим папку, где будем хранить шейдеры. Назовем ее
Shaders. Далее создадим шейдер: правый клик по папке
Shaders>Create>Shader>Unlit Shader. Назовем шейдер xgmSkin.

#3 Vertex and Fragment Shader — Unity — DevTribe: инди-игры, разработка, сообщество

Перед нами открылось окно редактора с содержанием стандартного Unlit
Shader'а. Выделяем все и смело удаляем. Начнем, как говориться, "с чистого листа".
Из предыдущей статьи мы уяснили, что в Unity шейдер пишется внутри
SubShader'а. Так-что давайте сначала напишем "фундамент".

Shader "MyShaders/xgmSkin" // путь и имя шейдера в выпадающем окне 
материала
{
  Properties // отображаемые в инспекторе свойства
   { 
    
   }
   SubShader 
   {
     Pass 
      {
        CGPROGRAM
        // тут будет CG код
        CGEND
      }
   }
  Fallback "Diffuse" 
}

Начнем заполнять блок Properties. В нем мы обозначаем внешние
переменные, которые будут видны в окне материала в инспекторе. Здесь нам
многого не нужно, только текстурка. Пишем:

  Properties 
  {
    _xgmTex("Texture",2D) = "white" {} 
  }

Ну и всё, никаких тэгов писать не будем, нам подходят настройки по
дефолту, так что сразу спускаемся в блок CGPROGRAM.
В статье по теории я писал, что мы можем назначать, какие данные примет и
вернет шейдер при помощи семантики. Для удобства записи в CG программе
эти данные объединяют в структуры. Давайте опишем входящую(vertexInput) и
выходящую(vertexOutput) структуры для вертексного шейдера:

struct vertexInput // входящие данные
      {
        float4 vertex:POSITION; // позиция вершины в пространстве модели
        float2 uv:TEXCOORD0; // uv координаты данной вершины 
  
      };
      struct vertexOutput // выходящие данные
      {
       float4 position:SV_POSITION; // позиция 
       float2 uv:TEXCOORD0; // uv координаты
      };
После структур обязательно ставится знак ";"

Данные описаны, теперь самое время писать векртексный шейдер. Ой, чуть не забыл)
Для того, что бы обозначить функцию как вертексный или пиксельный
шейдер, мы должны назначить имена для этих функций в директиве #pragma.

#pragma vertex vert 
#pragma fragmet frag 

А вот собственно сам вертексный шейдер:

vertexOutput vert(vertexInput v) 
      {
        vertexOutput o; // создаем возвращаемую структуру 
        o.position = mul(UNITY_MATRIX_MVP,poss); // переводим координатыиз пространства модели в проекционное 
        o.uv = v.uv; // просто передаем uv координаты
        return o; 
      }

Пиксельный шейдер возвращает только цвет, так что нужды создавать
отдельную структуру для него у нас нет. Поэтому,назначаем семантику
прямо для самого возвращаемого значения функции frag(Семантика для цвета
COLOR или SV_Target ). Так же нам нужно вытащить текстуру из
Properties.Напомню, что имя внешней переменной должно быть такое-же, как в
Properties, что бы движок сам передал ей значение.

      uniform sampler2D _xgmTex; // внешняя текстура 

      fixed4 frag(vertexOutput v):SV_Target 
      {
        fixed4 col = tex2D(_xgmTex,v.uv);// берем цвет из текстуры по UV
 координатам
        return col;
      } 

Ну вот и всё, наш шейдер готов!

Shader "MyShaders/xgmSkin" 
{
  Properties 
  {
    _xgmTex("Texture",2D) = "white" {} 
  }

SubShader
 {
   Pass
   {
     CGPROGRAM 
     #pragma vertex vert // говорим имя у вертексного шейдера 
     #pragma fragment frag  // говорим имя пиксельного шейдера

      struct vertexInput 
      {
        float4 vertex:POSITION;
        float2 uv:TEXCOORD0;
      };
      struct vertexOutput
      {
       float4 position:SV_POSITION;
       float2 uv:TEXCOORD0;
      };
      vertexOutput vert(vertexInput v) 
      {
        vertexOutput o; // возвращаемая структура 
        o.position = mul(UNITY_MATRIX_MVP,v.vertex); // переводим координаты
        из пространства модели в проекционное 
        o.uv = v.uv; // просто передаем uv координаты
        return o;
      }
      uniform sampler2D _xgmTex; // внешняя текстура 

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по 
UV координатам
        return col;
      } 
     ENDCG  
   } 
  } 
  Fallback "Diffuse"
 } 

Пора применить его на объекте! Для того что-бы применить шейдер для
какого-либо объекта, нужно создать новый материал и назначить наш шейдер
в выпадающем окне материала(если вы не забыли, наш шейдер находится в MyShaders>xgmSkin)

#3 Vertex and Fragment Shader — Unity — DevTribe: инди-игры, разработка, сообщество

Теперь выберем нужную текстуру в окне материала.
Вуаля!

#3 Vertex and Fragment Shader — Unity — DevTribe: инди-игры, разработка, сообщество

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

    _Color ("LogoColor",Color) = (0,0,0,0)

И объявим его внутри шейдера в том-же месте, где объявляли текстуру

 uniform fixed4 _Color;

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

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по 
UV координатам
        return (1-col)*_Color;
      } 
1=(1,1,1,1); 0 = (0,0,0,0) //

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

#3 Vertex and Fragment Shader — Unity — DevTribe: инди-игры, разработка, сообщество

Итак, теперь мы, вроде, умеем делать простые-препростые шейдеры. Давайте
капнем немного глубже и сделаем нашей сфере дифузное освещение.
Вот формула, по которой рассчитывается освещенность для точки:
dif = max(0,(n*l)), где n - нормаль, l - направление света.

Заранее скажу, что рассчитывать освещение мы будет в мировых
координатах, следовательно, нормаль, которая дается в объектных
координатах придется переводить в мировые. Обычная матрица, которую мы
используем для частиц тут не подойдет, так-что для таких случаев
припасена встроенная инверсная матрица _World2Object.
Так-же хочу сказать о том, что в ShaderLab есть встроенная переменная
_WorldSpaceLightPos0. По названию можно понять, что это вектор, который
содержит мировые координаты источника света, но тут есть одна хитрость.
Если на карте используется только 1 источник света ( Direction light),
то тогда в эту переменную записывается вектор освещения, а если больше,
то ,действительно, положение источника света. В данном случае у нас один
источник, так что эта переменная нам подходит.
Еще кое-что.Как мы все знаем, семантика TEXCOORD используется для передачи
uv координат. Но, т.к. их может быть несколько штук, например,
TEXCOORD1,TEXCOORD2,TEXCOORD3..., ее удобно использовать, что-бы
передать нужные данные из вертексного шейдера в пиксельный, т.к. у
переменных во входящих/выходящих струтурах обязательно должна семантика.
Ну вот теперь вроде всё. Поехали!
Добавим в vertexInput строчку, которая будет запрашивать нормаль:

float3 norm:NORMAL;

И в vertexOutput переменную для хранения мировых координат нормали:

       float3 worldNormal:TEXCOORD1;

Далее идем в вертексный шейдер и переводим нормаль из объектного в
мировые координаты:

        o.worldNormal = mul(_World2Object,v.norm);

Ну и рассчитаем силу освещения в пиксельном шейдере:

      fixed4 frag(vertexOutput v):SV_Target
      {
        fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по UV координатам
        float3 l = normalize(_WorldSpaceLightPos0); // нормализуем вектор освещения
        float3 n = normalize(v.worldNormal); // нормализуем вектор нормали 
        float dif = max(0.0,dot(n,l)); // рассчитываем освещенность пикселя 
        return ((1-col)*_Color)*dif; 
      } 

Ну вот как-то так. Теперь, если мы перейдем в юнити и изменим
направление лучей у Direction light'а, то заметим, что участки с
противоположной стороны от света затеняться.

#3 Vertex and Fragment Shader — Unity — DevTribe: инди-игры, разработка, сообщество

Shader "MyShaders/xgmSkin"
{
Properties
{
_xgmTex("Texture",2D) = "white" {}
_Color ("LogoColor",Color) = (0,0,0,0)
}

SubShader
{
Pass
{
Cull Off

CGPROGRAM
#pragma vertex vert // говорим имя у вертексного шейдера
#pragma fragment frag // говорим имя пиксельного шейдера

struct vertexInput
{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
float3 norm:NORMAL;
};
struct vertexOutput
{
float4 position:SV_POSITION;
float2 uv:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
vertexOutput vert(vertexInput v)
{
vertexOutput o; // возвращаемая структура
o.position = mul(UNITY_MATRIX_MVP,v.vertex); // переводим координаты из пространства модели в проекционное
o.uv = v.uv; // просто передаем uv координаты
o.worldNormal = mul(_World2Object,v.norm); // переводим нормаль в мировые к-ты
return o;
}
uniform sampler2D _xgmTex; // внешняя текстура
uniform fixed4 _Color;

fixed4 frag(vertexOutput v):SV_Target
{
fixed4 col = tex2D(_xgmTex,v.uv); // берем цвет из текстуры по UV координатам
float3 l = normalize(_WorldSpaceLightPos0); // нормализуем вектор освещения
float3 n = normalize(v.worldNormal); // нормализуем вектор нормали
float dif = max(0.0,dot(n,l)); // рассчитываем освещенность пикселя
return ((1-col)*_Color)*dif;
}
ENDCG

}
}
Fallback "Diffuse"
}

Итог:

http://devtribe.ru/ext-files/562/174812/qwerty.unity3d

To be continued ...

P.S. спонсоры данных статьей - кофе и свободное время. Спасибо им за то что они есть.

Смотрите также:


Комментарии

Здесь еще никто не оставил комментарий

Справка