В каком разрешении рисовать спрайты для мобильной 2D игры?

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

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

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

Для этого определимся какие же разрешения экранов и соотношения сторон наиболее популярны на текущий момент. Я для этого воспользовался открытой статистикой от команды Unity, посмотреть её можно здесь. Вот данные актуальные на момент написания статьи:

Разрешения экранов

(далее…)

Отображение поля ScriptableObject в Custom Inspector’е некоторого компонента

Предположим, у нас есть некоторый класс унаследованный от MonoBehaviour, назовём его SODataBehaviour.

using UnityEngine;

namespace Triks.SO {
	public class SODataBehaviour : MonoBehaviour {

		/// <summary>
		/// Экземпляр класса SOData
		/// </summary>
		[SerializeField, Tooltip("Экземпляр класса SOData")]
		private SOData scriptableObjectData;

		/// <summary>
		/// Поле типа int
		/// </summary>
		[SerializeField, Tooltip("Поле типа int")]
		private int someInt = 5;
	}
}

В нём есть поле, тип которого — класс унаследованный от ScriptableObject, его мы назовём SOData.

using UnityEngine;

namespace Triks.SO {

	/// <summary>
    /// Класс характеризующий 
    /// </summary>
	[CreateAssetMenu(menuName = "Triks/SO Data")]
	public class SOData : ScriptableObject {
		
		/// <summary>
        /// Скорость передвижения
        /// </summary>
		[SerializeField, Range(1, 15), Tooltip("Скорость передвижения")]
		private float speed = 1;

		/// <summary>
        /// Возвращает скорость передвижения
        /// </summary>
		public float Speed { 
			get { return speed; }
		}

		/// <summary>
        /// Урон наносимый от контакта
        /// </summary>
		[SerializeField, Range(0.1f, 50), Tooltip("Урон наносимый от контакта")]
		private float contactDamage = 10;

		/// <summary>
        /// Возвращает урон наносимый от контакта
        /// </summary>
		public float ContactDamage {
			get { return contactDamage; }
		}
		
		/// <summary>
        /// Описание данных
        /// </summary>
		[SerializeField, Tooltip("Описание данных")]
		private string description;

		/// <summary>
        /// Возвращает описание данных
        /// </summary>
		public string Description {
			get { return description; }
		}
	}
}

По умолчанию в инспекторе это будет выглядеть так:

(далее…)

Debug.Log() и кто его вызвал

Порой, бывает удобно вывести в консоль отладки полный путь с иерархией в сцене того объекта, который это сообщение вызвал:

А вот как это можно сделать:

using UnityEngine;

public class Test : MonoBehaviour {

	public static string GetHierarchyPath(Component inComponent) {
		if (inComponent) {
			string path = inComponent.name;

			while (inComponent && inComponent.transform.parent) {
				inComponent = inComponent.transform.parent;
				path = inComponent.name + "/" + path;
			}
			return path;
		}	

		return string.Empty;
	}

	void Start () {
		Debug.Log("I am here -> " + GetHierarchyPath(this));				
	}
}

Расширение DebugGraphs для редактора Unity5

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

С ним нет нужды вычленять из консоли кучу значений выведенных через Debug.Log(), за изменением всех отслеживаемых параметров можно следить визуально и для этого вам даже не придётся писать код :D (но кому очень хочется, такая возможность предусмотрена).

Основные фичи:

  • Легенда для графиков
  • Компонент для добавления графиков без написания кода
  • Настраиваемое количество графиков, их цветов, масштаба и смещения по осям
  • Масштабируемая сетка (масштаб можно менять как отдельно для каждой оси, так одновременно и для них обоих)
  • Автоматическое слежение за новыми точками в Play режиме
  • Открыт исходный код
  • Экспорт графиков в CSV файл

(далее…)

Monsters Gallery Puzzle

Monsters Gallery PuzzleСпешу сообщить что я наконец-то выпустил свою новую игру Monsters Gallery Puzzle!

На данный момент игра доступна для Android устройств: google-play-badge-150

В ближайшем будущем планируется выход игры в App Store.

Ну всё, теперь ловите порцию скриншотов и геймплейное видео ;)

Качаем, играем и оставляем отзывы ;)google-play-badge-150

Git и Unity

Для того что бы вести разработку на Unity и использовать при этом Git, следует сделать следующее:

  • Настроить редактор для отображения meta-файлов и для хранения всех изменений в этих meta-файлах:

Git_Unity_1 (далее…)

Баг метода isOpen() в QSqlDatabase

Наткнулся я на один не приятный баг в Qt 5.4. Выяснил вот, что в классе QSqlDatabase метод isOpen(), отвечающий за проверку соединения с базой данных, НЕ РАБОТАЕТ. Он всегда возвращает true, даже если соединение с базой оборвалось. Метод гугления показал, что я не единственный кто напоролся на этот баг. И главное, народ о нём уже репортил разработчикам в более ранних релизах Qt (если память не изменяет в 4.8), но баг всё ещё присутствует. =/

Выход из ситуации следующий: используйте API той БД с которой работаете. Ниже пример того, как я это сделал через MySQL API (Си’шный).

#include "mysql.h"

// функция для замены метода isOpen()
bool SQLmanager::haveConnection() {

	QVariant handle = db.driver()->handle();

	if ((QString)handle.typeName() == (QString)"MYSQL*") {
		MYSQL *nativeHandle = *static_cast<MYSQL **>(handle.data());
		if (nativeHandle != 0) { // если удалось получить указатель
			if (mysql_ping(nativeHandle) == 0) // mysql_ping возвращает 0, если соединение есть, иначе возвращает код ошибки
				return true;
			else
 				return false;
 		}/* else {
 			qDebug() << "не удалось получить указатель MYSQL*";
 		}*/
	}
	return false;
}