Пользователь
2,4
рейтинг
7 октября 2014 в 07:04

Разработка → Unity3D tips and tricks



Было уже несколько статей подобного плана, где рассказывались разные трюки и приёмы для Unity. Что-то было совсем очевидно и только для новичков, что-то для более продвинутых товарищей. Хочу внести свою скромную лепту.


1. Подсказки по переменным.



Когда проект маленький это не актуально, но когда проект большой и над ним работает много человек можно забыть, за что именно отвечает та или иная переменная, которую задаешь в редакторе. Правильное именование помогает лишь частично, так как слишком короткое. Можно конечно писать Custom Editor и там делать подсказки для каждого типа, но для каждого класса это слишком накладно. Следующий способ позволяет решить такую задачу. Для этого мы делаем 2 классика:

TooltipAttribute.cs

using UnityEngine;

public class TooltipAttribute : PropertyAttribute
{
	public readonly string text;
	
	public TooltipAttribute(string text)
	{
		this.text = text;
	}
}


TooltipDrawer.cs

#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(TooltipAttribute))]
public class TooltipDrawer : PropertyDrawer
{
	public override void OnGUI(Rect position, SerializedProperty prop, GUIContent label) {
		var atr = (TooltipAttribute) attribute;
		var content = new GUIContent(label.text, atr.text);
		EditorGUI.PropertyField(position, prop, content);
	}
}
#endif


Теперь, если нам надо чтобы в стандартном инспекторе была подсказка по нужной нам переменной — просто делаем так:

	[Tooltip("Первоначальный цвет объекта")]
	public Color color;

	[Tooltip("Скорость объекта, если отрицательная - движется задним ходом")]
	public float speed;


Результат:

На скриншоте почему-то не видно курсора мышки, подсказка появляется при наведении.

Перфекционисты, чтобы не добавлять мусор в релизный код, могут делать так:
#if UNITY_EDITOR
	[Tooltip("Скорость объекта, если отрицательная - движется задним ходом")]
#endif
	public float speed;


Хотя, на мой взгляд, это уже излишне.

Теперь, даже если через год-два надо что-то подправить в редакторе Вы быстро вспомните что это за переменная.

Вот здесь есть самурайская коллекция PropertyDrawer. Комменты на японском языке, но в принципе всё понятно.

2. Nullable types



Иногда бывает необходимо проверить наличие значения у переменной. Ну например вот так:

public class Character : MonoBehaviour 
{
    Vector3 targetPosition;
 
    void MoveTowardsTargetPosition()
    {
        if(targetPosition != Vector3.zero)
        {
            //Move towards the target position!
        }
    }
 
    public void SetTargetPosition(Vector3 newPosition)
    {
        targetPosition = newPosition;
    }
}


Но что, если нашему герою надо прийти в точку (0, 0, 0)? Тогда такой код не подходит.

Надо использовать nullable type. Просто добавляем знак '?' в конце к типу, и чтобы проверить наличие используем HasValue, а чтобы получить значение — Value.

public class Character : MonoBehaviour 
{
    //Notice the added "?"
    Vector3? targetPosition;
 
    void MoveTowardsTargetPosition()
    {
        if (targetPosition.HasValue)
        {
            //Move towards the target position!
            //use targetPosition.Value for the actual value
        }
    }
 
    public void SetTargetPosition(Vector3 newPosition)
    {
        targetPosition = newPosition;
    }
}


3. Personal Log.



Этот хинт может пригодится для отладки AI, по крайней мере в моём случае это было так. Смысл хинта совсем прост — просто чтобы не рыть огромный общий лог заводим каждому юниту персональный, в нашем случае это строка (string localLog). Все важные события из жизни монстра пишем туда, а для просмотра надо просто выделить монстра в редакторе. Код для того, чтобы отображался персональный лог в инспекторе:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(Monster))]
public class MonsterEditor : Editor {
	Vector2 scrollPos = new Vector2(0, Mathf.Infinity);

	public override void OnInspectorGUI()
	{
		serializedObject.Update();
		Monster monster = (Monster)target;

		if (Application.isPlaying) {
			scrollPos = GUILayout.BeginScrollView (
				scrollPos, GUILayout.Height (250));
			
			GUILayout.Label (monster.localLog);
			
			GUILayout.EndScrollView ();

			if (GUILayout.Button ("Clear"))
				monster.localLog = "";
		}

		serializedObject.ApplyModifiedProperties();
		DrawDefaultInspector();
	}
}


Вот, в общем то, и всё. Теперь мы видим всё что монстр думал про нас и других монстров. Такой вот простой хинт облегчает отладку.

Буду рад, если кому-то это поможет.
Игорь @Igor_Sib
карма
21,0
рейтинг 2,4
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (9)

  • +2
    В Unity 4.5 и старше уже доступен и работает атрибут Tooltip. Есть даже возможность вешать методы на правый клик по переменным. См статью выше.
    • 0
      Спасибо, не знал про это.
  • –1
    За троллинг типами — пять баллов =) Но важен не сам тип, а число, которое туда записано =)))
    • +5
      Вас, как специалиста в этом вопросе, не смутило, что типы signed, а не unsigned?
  • 0
    Надо использовать nullable type.

    Признаться, не очень люблю нуллаблы, для меня они как лайфхак, или костыль. Но это чистое ИМХО.
    На самом деле такие ситуации, как описана выше, обычно не возникают, потому как в таких случаях надо использовать стейт машину. Я бы, например, попробовал сделать сеттер для поля targetPosition, который менял бы состояние объекта из Idle в Moving когда в него пишут значение. К примеру.
    Хотя, признаться, Ваше решение также имеет право на жизнь.
    • 0
      Это же просто для примера. Естественно именно для такой задачи (движение в точку) будет другая реализация, я бы сделал список тасков, можно и по другому — всё зависит от задачи.
  • +1
    На скриншоте почему-то не видно курсора мышки, подсказка появляется при наведении.
    Если вы под Windows просто нажимали Print Screen, то курсор не сохранится. Для сохранения надо использовать сторонние программы, например XnView (Инструменты -> Захват экрана).
    • 0
      На Маке делал скриншот, стандартным методом.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.