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


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

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

Следующие 30  »
DJmp-3

VA - Beatport Top 100 Techno [July] (2016)

Суббота, 13 Августа 2016 г. 08:41 (ссылка)
djmp-3.com/electronic/3571-...-2016.html

VA - Beatport Top 100 Techno [July] (2016)


 

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

VA - Starseed (2016/FLAC)

Вторник, 09 Августа 2016 г. 21:49 (ссылка)
djmp-3.com/dts/3516-va-star...-flac.html

VA - Starseed (2016/FLAC)


 

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

Делаем работу нашего гейм-дизайнера в Unity удобнее и приятнее

Пятница, 05 Августа 2016 г. 15:03 (ссылка)

Добрый день, Хабр. В эфире снова я, Илья Кудинов. В свободное от основной работы время я занимаюсь разработкой игрушек на Unity 3D и решил в качестве эксперимента написать статью об одной из проблем, с которой столкнулась наша команда. Я являюсь основным разработчиком, и наш гейм-дизайнер в «гробу видал» копание в моем коде с какой бы то ни было целью (разделение труда — одно из величайших достижений цивилизации), значит, моя обязанность — предоставить ему все необходимые рычаги управления и настройки геймплея в виде удобных визуальных интерфейсов. Благо Unity сам по себе имеет достаточно удобные (кхе-кхе) готовые интерфейсы и ряд методов их расширения. И сегодня я расскажу вам о некоторых приемах, которые делают жизнь нашего гейм-дизайнера проще и удобнее, а мне позволяют не биться головой о клавиатуру после каждого его запроса. Надеюсь, они смогут помочь каким-нибудь начинающим командам или тем, кто просто упустил эти моменты при изучении Unity.



Сразу скажу, что наша команда все еще активно учится и развивается, хоть мы уже и выпустили дебютную игру. И если «дедлайны не горят», то я предпочитаю разбираться в каких-то вещах сам, а не обращаться к экспертам и различным best practices. Поэтому что-то из рассказанного мною может оказаться не оптимальным или банальным. Буду очень рад, если в таких случаях вы подскажете мне более удобные решения в комментариях и личных сообщениях. Ну и в целом информация здесь скорее базового уровня.



Код для Unity я пишу исключительно на C#, поэтому все выкладки в статье будут именно на этом языке.



Singleton-объекты



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


  • для изменения каких-либо параметров гейм-дизайнерам придется лазить напрямую в код, а они это очень не любят;

  • будет сложнее использовать ссылки на любые ассеты в Unity (префабы, текстуры и т.д.), так как придется загружать их через Resources.load(), а такой код поддерживать существенно труднее, чем те ссылки, которые можно создавать через интерфейс Unity.



Решение проблемы? Наследовать ваши классы от MonoBehaviour и создавать для каждого из них объект в сцене. Минусы этого подхода? При обращении к этим объектам придется пользоваться извращенными вызовами типа FindObjectOfType() или даже GameObject.Find(”GameController”).GetComponent(). Ни один уважающий себя разработчик делать так на каждом шагу не захочет. Дополнительные проблемы и возможные ошибки начинают возникать при необходимости переносить такие объекты между сценами или при возникновении нескольких объектов с таким классом (либо их полном отсутствии).

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

Наше решение выглядит следующим образом («костяк» класса я когда-то давно нашел на просторах интернета и слегка доработал для собственного удобства):



using UnityEngine;
public class Singleton : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;

public void Awake()
{
// Если в сцене уже есть объект с таким компонентом, то
// он пропишет себя в _instance при инициализации
if (!_instance) {
_instance = gameObject.GetComponent();
} else {
Debug.LogError("[Singleton] Second instance of '" + typeof (T) + "' created!");
}
}

public static T Instance
{
get
{
if (_instance == null) {
_instance = (T) FindObjectOfType(typeof(T));

if (FindObjectsOfType(typeof(T)).Length > 1) {
Debug.LogError("[Singleton] multiple instances of '" + typeof (T) + "' found!");
}

if (_instance == null) {
// Если в сцене объектов с этим классом нет - создаём
// новый GameObject и лепим ему наш компонент
GameObject singleton = new GameObject();
_instance = singleton.AddComponent();
singleton.name = "(singleton) " + typeof(T).ToString();
DontDestroyOnLoad(singleton);
Debug.Log("[Singleton] An instance of '" + typeof(T) + "' was created: " + singleton);
} else {
Debug.Log("[Singleton] Using instance of '" + typeof(T) + "': " + _instance.gameObject.name);
}
}
return _instance;
}
}
}




Как этим пользоваться? Наследуем свои классы от Singleton, указав самого себя в шаблоне:

 public class GameController : Singleton
В дальнейшем мы сможем обращаться к полям и методам нашего класса как GameController.Instance.MakeEverybodyHappy() в любом месте кода. Чтобы создавать ссылки на ассеты, достаточно добавить этот компонент на любой объект в сцене и настраивать его привычным образом (и сохранять в префаб для верности). Мы используем объект Library в корне сцены для хранения всех Singleton-классов, настройка которых может понадобиться нашему гейм-дизайнеру, чтоб ему не приходилось их искать по всей сцене.



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

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




Кастомные поля инспектора класса



Итак, гейм-дизайнер получил свои визуальные интерфейсы и начал творить геймплей. И достаточно быстро начал ненавидеть меня, невинного разработчика, за все неудобства, которые на него наваливаются. Массив сериализованных объектов? Многомерные массивы? Почему это все настолько неудобно настраивать? Как бы вы ни старались сделать универсальную и расширяемую систему на стороне кода, ваш гейм-дизайнер предпочел бы видеть минимальное количество выпадающих списков и уж тем более массивов элементов с названиями вроде Element 73. Но разве мы можем что-то с этим поделать?

На самом деле можем. Предположим, в нашей игре появляются настройки сложности, и в данный момент вариантов три. Но, возможно, станет больше. Поэтому мы смотрим в будущее и для упрощения дальнейшего ВОЗМОЖНОГО увеличения количества сложностей создаем вот такой замечательный класс «зависящих-от-сложности-интов» и заменяем в нужных местах обычные инты на него:



[System.Serializable]
public class DifDepInt
{
public int[] values = {0, 0, 0};

static public implicit operator int (DifDepInt val)
{
return val.Get();
}

public int Get()
{
return values[GameConfig.Instance.difficulty];
}
}




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



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





Да, однозначно, это не очень интуитивно и удобно. Давайте сделаем так, чтобы все выглядело иначе! Для этого мы воспользуемся вышеназванной «плюшкой» Unity — возможностью создавать кастомных инспекторов для отображения различных классов. Это достаточно хитрая система, позволяющая вам делать практически все что угодно, но в ней не так просто разобраться с первого взгляда (с самого начала она меня отпугнула, и поэтому какое-то время мы-таки страдали со стандартным инспектором, но в конце концов момент истины настал).

Итак, мы пишем следующий код:



#if UNITY_EDITOR
using UnityEditor;

[CustomPropertyDrawer(typeof(DifDepInt))]
public class DifDepIntDrawer : PropertyDrawer
{
int difCount = 3;

public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);

Rect contentPosition = EditorGUI.PrefixLabel(position, label);
contentPosition.width *= 1 / difCount;
float width = contentPosition.width;

SerializedProperty values = property.FindPropertyRelative ("values");

for (int i = 0; i < difCount; i++) {
EditorGUI.PropertyField (contentPosition, values.GetArrayElementAtIndex(i), GUIContent.none);
contentPosition.x += width;
}

EditorGUI.EndProperty();
}
}
#endif




Давайте разберемся, что тут происходит. Директива компилятора #if UNITY_EDITOR сообщает Unity, что она должна компилировать этот класс только во время разработки в редакторе. В противном случае она будет пытаться собрать этот код при сборке билда игры, а модуль UnityEditor там недоступен целиком, и это может вызвать сбивающие с толку ошибки.

[CustomPropertyDrawer(typeof(DifDepInt))] говорит Unity, что для отрисовки полей классов типа DifDepInt ей нужно использовать предоставленный ниже код вместо стандартного. Таких директив можно указать сколько угодно подряд для всех DifDep-классов, которые вам понадобятся — сам код кастомного редактора написан так, что примет любые классы, имеющие в себе массив элементов под названием values, поэтому этот класс у меня обслуживает и int, и float, и даже Sprite и GameObject.

Мы перегружаем метод OnGUI(), который и занимается отрисовкой области редактирования поля в инспекторе. Unity вызывает его иногда несколько раз за кадр — это нужно иметь в виду. Не забываем оставлять методы EditorGUI.BeginProperty() и EditorGUI.EndProperty(), без них корректно работать ваш код не будет.

Остальной код достаточно интуитивно понятен, если заглянуть в документацию Unity. Вместо магии с contentPosition можно использовать методы отрисовки из класса EditorGUILayout, а не EditorGUI, однако они не всегда ведут себя очевидным образом и в некоторых плохих случаях разбираться с ними себе дороже.

Ради чего же мы этим занимались? Смотрите, какая красота!





Это однозначно удобнее того, что было. Возможности, которые дает подобный функционал, практически безграничны — вы можете отображать самые сложные структуры максимально удобным для редактирования способом. Но не думайте, что гейм-дизайнер будет вам благодарен. Он примет это как должное, я вам гарантирую (:



Кастомные редакторы целого класса



Окей, красиво рисовать отдельные поля мы научились, а можем ли мы рисовать что-то, что охватывает весь класс? Конечно же да! Например, параметры всех грейдов отдельно взятого вида оружия мы задаем вот так:





Помимо редактирования полей здесь присутствует еще и калькулятор, значения в котором изменяются автоматически при изменении параметров оружия (на самом деле они read-only, вид инпутов они имеют только для консистентности и удобства выравнивания).

Как же сделать что-то подобное? Очень просто и схоже с тем, что мы делали до этого! Продемонстрирую на простом примере— добавлении простенького калькулятора DPS перед всеми остальными полями в классе поведения монстра:



#if UNITY_EDITOR
using UnityEditor;

[CustomEditor(typeof(EnemyBehaviour), true)]
public class EnemyCalculatorDrawer : Editor
{
public override void OnInspectorGUI() {
EnemyBehaviour enemy = (EnemyBehaviour)target;
float dps1, dps20;

dps1 = enemy.damageLeveling.Get(1) / enemy.getAttackDelay(1);
dps20 = enemy.damageLeveling.Get(20) / enemy.getAttackDelay(20);

GUIStyle myStyle = new GUIStyle ();
myStyle.richText = true;
myStyle.padding.left = 50;
EditorGUILayout.LabelField("Calculator", myStyle);
EditorGUILayout.LabelField("DPS on level 1: " + dps1.ToString("0.00"), myStyle);
EditorGUILayout.LabelField("DPS on level 20: " + dps20.ToString("0.00"), myStyle);
EditorGUILayout.Separator();

base.OnInspectorGUI();
}
}
#endif




Ситуация очень похожая: сначала мы сообщаем Unity о желании заменить отрисовщик для этого класса с помощью директивы [CustomEditor(typeof(EnemyBehaviour), true)]. Затем переопределяем метод OnInspectorGUI() (да, в этот раз не OnGUI(), потому что разработчик должен страдать), пишем в нем свою кастомную логику (унаследованное от класса Editor поле под названием target содержит в себе ссылку на отображаемый объект как на Object) и затем вызываем base.OnInspectorGUI(), чтобы Unity отрисовал все остальные поля так же, как и обычно. GUIStyle позволяет нам изменять внешний вид отображаемых данных. В этом случае я использовал методы из EditorGUILayout просто потому, что здесь совершенно не надо было беспокоиться о выравненном позиционировании.

Итог же выглядит так:



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



Всякие мелочи



Конечно, можно делать огромное количество других вещей, чтобы спасти глаза и мозг ваших коллег. Unity предлагает целый набор директив для того, чтобы превратить простыню public-полей в структурированное целое. Самая важная из них, это, конечно, [HideInInspector], которая позволяет скрыть public-поле из инспектора. И больше не нужно вопить: «Пожалуйста, не трогайте эти галочки, они служебные!», и затем все равно часами разбираться, почему все монстры внезапно начали ходить задом наперед. Помимо этого есть еще приятные вещи вроде [Header(«Stats»)], которые позволяют отображать аккуратный заголовок перед блоком полей, и [Space], который просто делает небольшой отступ между полями, помогая разбивать их на смысловые группы. Все три эти директивы нужно писать непосредственно перед объявлением public-поля (если вы поставите [Header()] перед приватным полем, то ругаться Unity не станет, но никакого заголовка не отобразит).

Небольшая подсказка: если ваш сериализуемый объект имеет в себе string-поле под названием name, то когда вы засовываете несколько таких объектов в публичный массив, его “имя” будет отображаться вместо неинтуитивного Element X в инспекторе.

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



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



Товарищи разработчики-программисты, в совершенстве владеющие традиционным китайским языком, — глубокий поклон вам и извинения за такие предрассудки.
Original source: habrahabr.ru.

https://habrahabr.ru/post/307170/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

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

Расширение функционала Scene View в Unity3D. Перехват событий

Вторник, 13 Июля 2016 г. 00:48 (ссылка)

Scene View в Unity3D является одним из самых необходимых элементов интерфейса. Каждый, кто хоть раз запускал Unity3D пользовался Scene View для визуальной расстановки объектов на сцене, а также для их настройки. Расширение функционала Scene View может понадобиться для создания собственного редактора уровней, редактирования mesh’а, создания собственных gizmos и много другого. Стоит заметить, что при использовании Terrain в вашем проекте, его редактирование (рисование текстур, изменение высот, а также посадка деревьев и растительности) осуществляется при помощи Scene View.



Для того, чтобы иметь возможность писать скрипты работающие в Scene view в первую очередь класс с которым вы работаете должен быть унаследован от Editor или EditorWindow, что подразумевает подключение namespace UnityEditor. Это дает доступ к нескольким «магическим» методам Unity3D, таким как OnGUI() и OnSceneGUI(). Метод OnSceneGUI дает возможность Editor'у управлять событиями Scene View.





Небольшое лирическое отступление. Среди разработчиков бытует мнение, что «магические» методы (Update, Start, OnSceneGUI и другие) реализованы по средствам System.Reflection в C#, однако есть информация, что это не так, и за их работу стоит благодарить C++ ядро Unity3D. В целом статья будет полезна всем, кто грешит множественными Update() в своем коде.



Вернемся к перехвату событий. Идея заключается в том, чтобы обозначить объект, для которого мы разрабатываем функционал, как элемент интерфейса Unity, на равне с Label или Button из IMGUI.



В api существует класс Event, который используется для различных GUI событий, например нажатия клавиш, кнопок мыши, событий рендеринга и layout’а Unity.



Помимо Event для перехвата кликов понадобится такая вещь как control. В качестве control в Unity может выступать любой элемент IMGUI. К примеру Button или Label. Для того, чтобы ваш объект перехватывал клик, необходимо сказать Unity, что он тоже является control и собирается участвовать в обработке событий. Для этого воспользуемся классом GUIUtility.

Каждый control должен обладать собственным уникальным id, с помощью которого Unity получит всю необходимую информацию о нем. id представляет собой int, однако стоит заметить, что он должен быть уникальным. Вы можете сгенерировать случайное число (отличное от 0) и считать его id вашего control, но при этом нет гарантии, что в системе уже нет control с таким же id, и в таком случае клик уйдет не к тому элементу, на который вы рассчитывали. Для создания уникального id используем метод из класса GUIUtility

public static int GUIUtility.GetControlID(FocusType focus) 


Параметр, принимаемый на вход этим методом отвечает за возможность control получать какой-либо ввод с клавиатуры. Информацию о нем, можно получить в документации. Так как ввод с клавиатуры в случае использовании Scene View не нужен, подойдет значение FocusType.Passive.

 int controlId = GUIUtility.GetControlID(FocusType.Passive); //получение уникального id для нашего элемента интерфейса.


Теперь, когда мы разобрались с получением id, настало время разобраться с перехватом событий. Мы можем получить информацию о текущем событии с помощью свойства Event.current. Чтобы получить тип события, которое произошло в Unity нужно сделать следующее

int controlId = GUIUtility.GetControlID(FocusType.Passive);
Event.current.GetTypeForControl(controlId)

https://habrahabr.ru/post/305544/

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

Домашнее задание на лето: Топ-10 курсов Microsoft Virtual Academy

Понедельник, 11 Июля 2016 г. 12:25 (ссылка)

Прокачайте свои скиллы в виртуальной академии Microsoft MVA. В этом обзоре вы найдете самые интересные курсы для новичков: с чего начать разработку на C#, Python, как использовать Xamarin, с чего начать разработку для Windows 10, как начать работу с ASP.NET Web API и облегчить работу благодаря Entity Framework, как научиться создавать игры с нуля, о разработке приложений виртуальной реальности и о создании доменной сети с нуля, а также основы работы с web-технологиями.









1. Увлекательное программирование на языке C#



Этот курс поможет вам научиться программировать на языке C# с нуля. Вас ждут практические задания, благодаря которым вы научитесь использовать C# для создания клиентских приложений, игр и мобильных приложений.



2. Xamarin для начинающих



Xamarin – это платформа для разработки мобильных кроссплатформенных приложений под iOS, Android и Windows. Благодаря Xamarin ваши приложения смогут использовать от 75% общей кодовой базы, написанной на С#. В этом курсе вы найдете пошаговую инструкцию по установке и настройке инструментов, узнаете как пользоваться эмуляторами, и пройдетесь по отладке и развертыванию приложений. Кстати, очень удобно разрабатывать приложения на Xamarin прямо в Visual Studio.



3. Разработка для Windows 10 для начинающих



Все вопросы о создании приложения для Windows 10 на универсальной платформе Windows (UWP) – в одном курсе. Вы узнаете о XAML, управлении макетами, сетками, монетизации приложений с помощью рекламы и это далеко не все.



4. Основы построения доменной сети



В рамках курса вы узнаете как создать доменную сеть, добавить в нее пользователей и компьютеры, объединить их в группы и добавить подразделения. Также вы узнаете больше о службе Active Directory и типах сетей, которые можно создать используя операционные системы Microsoft.



5. Разработка приложений виртуальной и расширенной реальности на платформе Microsoft



В этом курсе собраны все вопросы построения приложений виртуальной реальности на платформе Microsoft – от базовых принципов формирования стереоизображения и отслеживания поворотов головы до более глубоких вопросов высокоэффективной реализации расширенной реальности на C++/DirectX.



6. Введение в программирование игр на Unity



Научитесь создавать 2D-игры на Unity. Узнайте как создать персонажа, научиться им управлять и добавить в игру несколько уровней, наполненных приключениями. Курс также содержит в себе базовую информацию, необходимую для того, чтобы начать программировать на C# в рамках Unity.



7. Основы разработки сайтов и веб-приложений



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



8. Введение в программирование на Python (eng)



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



9. Web API: с чего начать (eng)



Есть вопросы о начале работы с ASP.NET Web API? Этот курс даст ответы на них, например вы узнаете больше о защите, атрибутах маршрутизации, поиске и устранении ошибок, а также о версионности ASP.NET Web API.



10. Создание модели данных Entity Framework для приложения ASP.NET MVC (eng)



Entity Framework предоставляет возможность работы с базами данных через объектно-ориентированный код C#. Этот инструмент позволит вам не углубляться в изучение деталей работы с СУБД SQL Server и синтаксиса T-SQL. Благодаря фреймворку вы сможете преобразовывать код C# в SQL-инструкции. Данный курс подразумевает знание по работе с ASP.NET MVC в Visual Studio, если у вас нет таких знаний, это отличный курс для изучения ASP.NET MVC.



Еще больше курсов для новичков можно найти на сайте Microsoft Virtual Academy в разделе Beginner.

Original source: habrahabr.ru.

https://habrahabr.ru/post/305294/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

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

Device Lab от Google: Project Tango

Пятница, 08 Июля 2016 г. 19:22 (ссылка)

В Лаборатории Google мы добрались до самого инновационного и многообещающего устройства. Project Tango - платформа компьютерного зрения для мобильных устройств, разработанная группой инженеров ATAP (Advanced Technology and Projects). Работающее на Android референсное устройство вы можете взять на тест и использовать данные платформы в своих приложениях. Навигация внутри помещений, построение 3D-карт помещений, измерение расстояний, дополненная реальность – лишь малая часть задач, которые вы можете решить при помощи Project Tango. О том, как разрабатывать приложения для платформы – в нашей статье. Читать далее

https://habrahabr.ru/post/304762/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best

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

DJ Atmosfera - Space Sound.Revival [Psy Trance Mix] (2016)

Четверг, 16 Июня 2016 г. 09:16 (ссылка)
djmp-3.com/electronic/3146-...-2016.html

DJ Atmosfera - Space Sound.Revival [Psy Trance Mix] (2016)


 

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

Следующие 30  »

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

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

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