Управление объектом для тачскрина

Управление персонажем или каким-нибудь транспортом, например, на платформе Android, как для двухмерного, так и трехмерного проекта. Итак, всё что нам нужно, это получить направление, в зависимости от движения пальца по некой области экрана. Эту саму область у нас будет определять обычная UI картинка, ее можно сделать вообще прозрачной и растянуть на пол экрана, а вторую часть экрана закрыть прозрачной кнопкой стрельбы, например. В Unity среди стандартных ассетов, есть подобный тип управления. Но нам важно научиться самим делать подобное, чтобы написать простой и легкий скрипт, без лишних строк кода, в котором намного проще разобраться.

Добавим на сцену изображение GameObject -> UI -> Image, важно еще учитывать, что у данной картинки обязательно должна стаять галочка Raycast Target:

Управление объектом для тачскрина

Далее, на эту картинку вешаем скрипт:

using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;

public class JoystickControl : MonoBehaviour, IDragHandler, IEndDragHandler, IPointerDownHandler, IPointerUpHandler {

	private enum AxisOption {HorizontalAndVertical, Horizontal, Vertical}
	private enum ControlMode {AnalogStick, DirectionalPad}
	private enum ProjectMode {Project3D, Project2D};
	[SerializeField] private AxisOption axes;
	[SerializeField] private ControlMode mode;
	[SerializeField] private ProjectMode project;
	public static Vector3 direction { get; private set; }

	void Awake()
	{
		direction = Vector3.zero;
	}

	Vector2 Round(Vector2 val)
	{
		float x = Mathf.Abs(val.x);
		float y = Mathf.Abs(val.y);

		if(x >= 0.5f && y >= 0.5f)
		{
			val.x = Mathf.Sign(val.x);
			val.y = Mathf.Sign(val.y);
			return val;
		}

		if(x > y)
		{
			val.x = Mathf.Sign(val.x);
			val.y = 0;
		}
		else
		{
			val.x = 0;
			val.y = Mathf.Sign(val.y);
		}

		return val;
	}

	void UpdateDirection()
	{
		Vector2 curDir = new Vector2(Input.touches[0].position.x - transform.position.x, Input.touches[0].position.y - transform.position.y).normalized;
		if(mode == ControlMode.DirectionalPad) curDir = Round(curDir);
		if(axes == AxisOption.Horizontal) curDir = new Vector2(Mathf.Sign(curDir.x), 0); 
		else if(axes == AxisOption.Vertical) curDir = new Vector2(0, Mathf.Sign(curDir.y));
		if(project == ProjectMode.Project3D) direction = new Vector3(curDir.x, 0, curDir.y); else direction = new Vector3(curDir.x, curDir.y, 0);
	}

	public void OnPointerDown(PointerEventData eventData)
	{
		UpdateDirection();
	}

	public void OnDrag(PointerEventData eventData)
	{
		UpdateDirection();
	}

	public void OnEndDrag(PointerEventData eventData)
	{
		direction = Vector3.zero;
	}

	public void OnPointerUp(PointerEventData eventData)
	{
		direction = Vector3.zero;
	}
}

Как мы видим сложностей особых нет. У скрипта имеется несколько опций. Можно выбрать для каких осей просчитывать направление. Есть выбор режима работы, один наподобие аналогового стика, а второй как для крестовины (восемь направлений) геймпада. И конечно же, в скрипте есть опция выбора проекта 3D или 2D.

Чтобы управлять, например, Rigidbody:

body.AddForce(JoystickControl.direction * speed, ForceMode2D.Impulse);

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

Скачать скрипт:

У вас нет доступа!
Тестировалось на: Unity 5.6.2

Комментариев 23

Офлайн
персонаж не двигается как это связать джойстик и персонажа?
Офлайн
не очень подробный урок
Добавьте демо сцену и видео
Офлайн
Light 1 июля 2017
Цитата: Давуд Ахмедов
не очень подробный урок

Подробней некуда, берешь направление с JoystickControl.direction и всё.
Офлайн
Light,
Как это?
Офлайн
Я не так хорошо разбираюсь в C# поэтому не и нужно демо сцена...
Офлайн
Light 1 июля 2017
Давуд Ахмедов, в статье есть пример использования.

Тестировать надо либо через Unity Remote, либо на андройде после сборки.
Офлайн
Light,
просто добавь демо сцену больше ничего я не прошу
ПОЖАЛУЙСТА
Офлайн
Light 2 июля 2017
Давуд Ахмедов, кинь мне в ЛС свою сцену, я посмотрю почему не работает.
Офлайн
Light,
давай лучше кину контроллер
И ты скажешь как это связывать
Офлайн
Light,
Кинуть не получается
У меня вот в чем проблема
Я сделал все как на уроке
Создал картинку Image
Поставил на нее скрипт как сказанно на уроке и что дальше
Тестировал ничего не работает
Офлайн
Этот джойстик подходит для Rotation?
Офлайн
Light 26 июля 2017
Андрей Овчаров, нет, тут надо писать другой скрипт.

Если очень нужно, можем под заказ. Обращаться в ЛС.
Офлайн
Vadim_Kuchma 12 августа 2017
Скажите, а что если я не использую axis'ы в управлении, т.к я взял за основу ваш урок "Меню привязки клавиш + сохранение"
Офлайн
Light 12 августа 2017
Vadim_Kuchma, тот скрипт не связан с axis.
Офлайн
Vadim_Kuchma 12 августа 2017
Вы не правильно поняли. Мне нужно чтобы этот скрипт управлялся через скрипт "привязки клавиш". Как я могу это сделать?
Офлайн
Light 12 августа 2017
Vadim_Kuchma, это скрипт управления для тачскрина, при чем тут привязка клавиш? Изъясняйся конкретней, что нужно в конечном итоге.
Офлайн
Vadim_Kuchma 13 августа 2017
Т.е эти скрипты конфликтовать не будут?
Офлайн
Vadim_Kuchma 13 августа 2017
И этот скрипт работает только в remote и сборке?
Офлайн
Light 13 августа 2017
Цитата: Vadim_Kuchma
Т.е эти скрипты конфликтовать не будут?

Не будут.

Цитата: Vadim_Kuchma
И этот скрипт работает только в remote и сборке?

Да.
Офлайн
Персонаж двигается только в право и вверх по диагонали. Что делать?
Офлайн
Light 13 августа 2017
Цитата: Вадим Кучма
Что делать?

Искать ошибки проекта, а в данном скрипте их нет.
Офлайн
Vadim_Kuchma 15 сентября 2017
А можно ли сделать чтобы скрипт не использовал axis?
Офлайн
Light 16 сентября 2017
Vadim_Kuchma, чем мешает тут axis?
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика