Перемотка времени в Unity

Что можно делать со временем в Unity? Точнее с процессами на сцене. Мы можем останавливать время, замедлять или ускорять. Всё это делается очень просто, с помощью лишь одной переменной Time.timeScale. Но если поставить отрицательное значение, то вместо перемотки времени назад, мы получим ошибку. И тут следует вывод, что надо сделать так, чтобы объекты повторили предыдущие действия. Собственно именно это и попробуем сделать. Записать параметры для конкретного объекта в массивы, а затем воспроизведение записи. Пример будет простой, и скорее подойдет для какой-нибудь легкой 2D игры. Впрочем, никто не мешает усовершенствовать скрипт.



Как это работает. На объекты с Rigidbody вешаем скрипт RecRew:

using UnityEngine;
using System.Collections;

public class RecRew : MonoBehaviour {

	private int arr = 500;
	private Rigidbody rig;
	private Transform tr;
	private Vector3[] pos;
	private Quaternion[] rot;
	private Vector3[] vel;
	private Vector3[] ang_vel;
	private int T_A;
	private int T_B;
	private int timer;

	void Awake () 
	{
		pos = new Vector3[arr];
		rot = new Quaternion[arr];
		vel = new Vector3[arr];
		ang_vel = new Vector3[arr];
		rig = GetComponent<Rigidbody>();
		tr = transform;
	}
	
	void Rec()
	{
		pos[T_A] = tr.position;
		rot[T_A] = tr.rotation;
		vel[T_A] = rig.velocity;
		ang_vel[T_A] = rig.angularVelocity;
		if(T_A < arr-1) T_A++; else T_A = 0;
	}
	
	void Rew()
	{
		if (timer > 1)
		{
			if(T_B > 0)
			{
				T_B--;
				timer--;
				T_A = T_B;
				tr.position = pos[T_B];
				tr.rotation = rot[T_B];
				rig.velocity = vel[T_B];
				rig.angularVelocity = ang_vel[T_B];
			}
			else
			{
				T_B = arr-1;

			}
		}
		else
		{
			Time.timeScale = 0;
		}
	}

	
	void FixedUpdate()
	{
		if(!TimeManager.rewind)
		{
			Rec();
			T_B = T_A;
			if(timer < arr-1) timer++;
		}
		else
		{
			Rew();
		}
	}
}

Здесь у нас несколько массивов, в которые записывается трансформ и физика объекта, запись идет непрерывно. А длинна массивов регулируется через arr. Чем больше будет размер массивов, тем больше потребуется ресурсов, поэтому не стоит увлекаться. Этот вариант заточен под 3D, для двухмерной игры просто заменить Rigidbody на Rigidbody2D.



Теперь на пустой объект добавим контроль перемоткой, скрипт TimeManager:

using UnityEngine;
using System.Collections;

public class TimeManager : MonoBehaviour {

	static private bool rew;
	public KeyCode key = KeyCode.Space;

	public static bool rewind
	{
		get{return rew;}
	}

	void Start () 
	{
	}

	void Update () 
	{
		if(Input.GetKey(key)) 
		{
			rew = true; 
		}
		else 
		{
			rew = false;
			Time.timeScale = 1;
		}
	}
}

После нажатия, в данном случаи "пробел", будут проигрываться записи массивов и по окончании, время - остановиться, пока удерживается клавиша. Затем опять всё возвращается в норму и продолжается запись. Стоит так же учитывать, что если например, делать перемотку времени для персонажа игрока, нужно отключать его управление, тут уже есть публичная переменная, которой мы определяем состояние перемотки.

Например:

if(!TimeManager.rewind)
{
	// управление персонажем
}

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

Офлайн
DayFall 21 октября 2015
Автор, грамматику текста проверяй, прежде чем выкладывать. Очень много ошибок.
По коду - стоит придерживаться единой нотации именования переменных и давать названия понятные.
T_A и T_B что это за колхоз?
bool rew - очень плохое название для булевой переменной.
Также, надо избавляться от вложенности if-ов. Процедуры делать короче размером.
Офлайн
Light 21 октября 2015
Цитата: DayFall

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

Жмем кнопочку "Сообщить об ошибке".

Цитата: DayFall
По коду - стоит придерживаться единой нотации именования переменных и давать названия понятные.
T_A и T_B что это за колхоз?
bool rew - очень плохое название для булевой переменной.
Также, надо избавляться от вложенности if-ов. Процедуры делать короче размером.

Замечательно, берем и исправляем на свое усмотрение. Никто не запрещает.
Офлайн
DayFall,
Сам-то смог бы сделать хоть часть всего этого?
Офлайн
Katerpiller 5 ноября 2016
Здравствуйте. А как сделать так чтобы персонаж останавливался где нужно на карте на определенное время (в секундах)? Мне для 2D проекта нужно чтобы чар подходил к определенному месту на карте. Управление тут же отрубается и чар останавливается на определенное время пока проговаривает свой монолог. Как только все проговорил, управление возвращается в руки игроку и пошел дальше. Монологи есть, управа есть. А вот как делать паузы не знаю)))
Офлайн
Light 5 ноября 2016
Katerpiller, паузы во время монолога? Хм, посмотрим, возможно это будет темой для публикации, но ничего не обещаю.
Офлайн
Katerpiller 5 ноября 2016
Light,
Да. Во время монолога.
Офлайн
Katerpiller 5 ноября 2016
Light,
Я брал монологи из простых пузырей (как в комиксах) вот здесь:
http://unity.grogansoft.com/speech-bubbles-and-popup-ui/
Если сделать из персонажей обычные прозрачные объекты с коллайдерами и прибацать к ним баблы с текстами чуть пошаманив с расположением баблов, то получается, что говорит сам герой. По карте расставил наставил этих объектов где надо и все. Очень удобно.
Офлайн
Frejk 22 октября 2017
Katerpiller,
как то это слишком "сложно"
Офлайн
mxstore 24 октября 2017
одного добавить 2D к Rigidbody мало.
rig.angularVelocity; - Не удается неявно преобразовать тип "UnityEngine.Vector3" в "float".
Офлайн
elamir 27 декабря 2017
mxstore,
Не могли бы сказать, как вы решили данную проблему?
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Яндекс.Метрика