Прокладывание маршрута мышкой

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


Чтобы всё заработало, потребуется совсем не много. Нужно создать префаб точки, который будет отмечать проложенный путь, это может быть обычный спрайт или меш, не важно. Главное, чтобы он лежал по умолчанию на плоскости XZ:

Прокладывание маршрута мышкой

То есть, "лицо" картинки должно быть развернуто вверх по Y, на камеру.



Далее, сам скрипт:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MouseNavi : MonoBehaviour {

	public string playerTag = "Player"; // тег объекта, который должен перемещаться
	public string groundTag = "GameController"; // тег объекта, на котором можно рисовать маршрут
	public float step = 3; // расстояние от точки до точки
	public int maxPathLength = 100; // макс точек маршрута
	public Transform dotPrefab; // префаб для визуализации точки

	private Vector3 position;
	private List<Transform> path = new List<Transform>();
	private static bool _done;
	private bool hitPlayer;
	private Transform player;
	private static Vector3 _dir;
	private int index;

	public static Vector3 direction
	{
		get{ return _dir; }
	}

	public static bool isDone
	{
		get{ return _done; }
	}

	void AddDot(Vector3 curPos, Vector3 normal) // добавление префаба на сцену
	{
		if(maxPathLength == path.Count) return;

		Transform t = Instantiate(dotPrefab) as Transform;
		t.position = curPos;
		t.rotation = Quaternion.FromToRotation(Vector3.up, normal);
		path.Add(t);
	}

	void DoAction() // основная функция, создание маршрута
	{
		if(isDone) return;

		RaycastHit hit;
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		if(Physics.Raycast(ray, out hit)) 
		{
			if(hit.transform.tag == playerTag)
			{
				player = hit.transform;
				position = hit.transform.position;
				hitPlayer = true;
			}

			if(hitPlayer && hit.transform.tag == groundTag)
			{
				float dist = Vector3.Distance(position, hit.point);

				if(dist >= step)
				{
					position = hit.point;
					AddDot(hit.point + hit.normal * 0.15f, hit.normal);
				}
			}
		}
	}

	void UpdatePath() // обновление вектора направления и массива
	{
		if(index == path.Count)
		{
			index = 0;
			path = new List<Transform>();
			_done = false;
		}

		if(!isDone) return;

		_dir = path[index].position - player.position;
		float dist = Vector3.Distance(path[index].position, player.position);
		if(dist <= 0.1f)
		{
			Destroy(path[index].gameObject);
			index++;
		}
	}

	void Update()
	{
		if(Input.GetMouseButton(0))
		{
			DoAction();
		}
		else if(Input.GetMouseButtonUp(0))
		{
			_done = true;
			hitPlayer = false;
		}

		UpdatePath();
	}
}

Вешаем его на любой удобный объект и настраиваем параметры.

Теперь, для объекта, который нужно двигать:

using UnityEngine;
using System.Collections;

public class NaviControl : MonoBehaviour {

	public float speed = 5;

	void Update()
	{
		if(!MouseNavi.isDone) return;

		transform.Translate(MouseNavi.direction.normalized * speed * Time.deltaTime);
	}
}

Простейший скрипт движения.

Работает всё просто. Пока ПКМ удерживаться, можно рисовать путь от объекта с указанным тегом. Если кнопку мыши отпустить, начинает работать второй скрипт и двигает цель по вектору маршрута.

Скачать демо:
Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.

Версия с вращением:
Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.

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

Офлайн
NickPDG 7 апреля 2016
Отлично! В одной стратегии по-моему SpringLobby видел подобную реализацию, но как с одним так и с группой юнитов, при этом их по этому принципу можно расставить по линии в любой форме, а с клавишей Shift проделать групповой путь растягивая каждые ключевые точки (линиями) группы юнитов - и группа движется синхронно в заданном направлении, при этом препятствия не очень нарушают путь следования. Чтобы понять о чем речь нужно увидеть! Возможно очень трудоёмкая реализация!
Офлайн
ArturST 16 марта 2017
Немогу разобраться но демо не работает
Офлайн
Light 16 марта 2017
ArturST, всё работает, проверено.
Офлайн
Lut
Lut 28 октября 2017
Подскакажите пожалуйста как сделать что бы персонаж поворачивался п сторону точки?
Офлайн
Fly Di 20 февраля 2018
Тоже дэмка не работает, подскажите пожалуйста в чем может быть дело?
Офлайн
Light 20 февраля 2018
Fly Di, у меня всё работает, никаких ошибок нет.
Офлайн
Fly Di 20 февраля 2018
Light,
Да в том и дело, что у меня тоже ошибок нет, ни в скрипте не при выполнении программы. При запуске видно что какие то процессы идут при нажатии мышкой, но визуально ни чего не происходит, точки пути не появляются.
Офлайн
Light 20 февраля 2018
Fly Di, проверял на версии 2017.3.1 никаких проблем не обнаружено. Что именно у тебя с редактором не так, мне это неведомо, я не волшебник.
Офлайн
Fly Di 20 февраля 2018
Light,
Все заработало)) спасибо. Сам не понял в чем дело. А все так и как сделать, что бы персонаж всегда носом по пути смотрел?
Офлайн
Light 21 февраля 2018
Fly Di, простая версия с вращением, добавлена в статью.
"Лицом" модели считается направление вектора Z данного объекта.
Офлайн
Fly Di 26 февраля 2018
Light,
Благодарю!
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика