Вы используете любой из двух способов и просто меняете Time.timescale , если хотите просмотреть его быстрее / медленнее и т. Д. В примере, нажав Пробел :
public class Example : MonoBehaviour
{
// Toggles the time scale between 1 (normal) and 0.5 (twice as fast)
// whenever the user hits the Space key.
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
if (Time.timeScale == 1.0f)
{
Time.timeScale = 0.5f;
}
else
{
Time.timeScale = 1.0f;
}
// Also adjust fixed delta time according to timescale
// The fixed delta time will now be 0.02 frames per real-time second
Time.fixedDeltaTime = 0.02f * Time.timeScale;
}
}
}
Для сопрограмм это работает без необходимости что-либо менять, потому что WaitForSeconds зависит от Time.timescale
:
Фактическое время приостановки равноданное время, умноженное на Time.timeScale.
Time.deltaTime
afaik not , на которое воздействует Time.timescale
, поэтому для более быстрого воспроизведения вам потребуетсяdo
private void Update ()
{
Timer += Time.deltaTime * (1 / Time.timescale);
if (timer >= 120)
{
//launch train, an so one conditions
//Or get timer variable in other script and compare time on update
}
}
Будет ли один Update
или несколько сопрограмм более производительным, во многом зависит от конкретного варианта использования.На самом деле, на самом деле это не заметно, пока у вас не будет примерно 10.000 сопрограмм (не указывайте здесь числа;)).
В вашем случае для поднятия только одного или нескольких событий лучше придерживатьсявместо этого с одним методом Update()
и вызовите событие или что-то в этом роде.
Но - почему бы просто не иметь один единственный сопрограмм вместо Update
вообще:
public class GlobalTimer : MonoBehaviour
{
public float Delay = 2.0f;
public UnityEvent onTimerDone;
// Unity allows to use Start as IEnumerator instead of a void
private IEnumerator Start()
{
yield return new WaitforSeconds(delay);
onTimerDone.Invoke();
}
}
, чем у вас есть только один вызванный метод и вы можете добавить обратные вызовы к этому таймеру, например
globalTimerReference.onTimerDone.AddListener(() => {
Debug.LogFormat("Timer of {0} seconds is done now.", globalTimerReference.Delay);
});
или через инспектор (как в UI.Button.onClick
).
ДляНесколько событий Я только что предложил быстрое и грязное решение, чтобы вы могли просто определить несколько событий через инспектор и добавить различные обратные вызовы и прочее:
public class GlobalTimer : MonoBehaviour
{
public List<UnityEvent> events;
public List<float> delays;
private void Start()
{
var validPairs = Mathf.Min(events.Count, delays.Count);
for (int i = 0; i < validPairs; i++)
{
StartCoroutine(InvokeDelayed(events[i], delays[i]));
}
}
private IEnumerator InvokeDelayed(UnityEvent unityEvent, float delay)
{
yield return new WaitForSeconds(delay);
unityEvent.Invoke();
}
}
Просто убедитесь, что для каждого события есть задержка всписок.В будущем вы, возможно, захотите написать правильный CustomEditor, чтобы редактировать этот более красивый в инспекторе.
Обновление
или вы можете взять мой: D
public class ExampleScript : MonoBehaviour
{
[SerializeField] private List<EventDelayPair> EventDelayPairs;
private void Start()
{
foreach (var eventDelayPair in EventDelayPairs)
{
StartCoroutine(InvokeDelayed(eventDelayPair.unityEvent, eventDelayPair.Delay));
}
}
private IEnumerator InvokeDelayed(UnityEvent unityEvent, float delay)
{
yield return new WaitForSeconds(delay);
unityEvent.Invoke();
}
[Serializable]
private class EventDelayPair
{
public UnityEvent unityEvent;
public float Delay;
}
}
[CustomEditor(typeof(ExampleScript))]
public class ExampleInspector : Editor
{
private SerializedProperty EventDelayPairs;
private ReorderableList list;
private ExampleScript _exampleScript;
private void OnEnable()
{
_exampleScript = (ExampleScript)target;
EventDelayPairs = serializedObject.FindProperty("EventDelayPairs");
list = new ReorderableList(serializedObject, EventDelayPairs)
{
draggable = true,
displayAdd = true,
displayRemove = true,
drawHeaderCallback = rect =>
{
EditorGUI.LabelField(rect, "DelayedEvents");
},
drawElementCallback = (rect, index, sel, act) =>
{
var element = EventDelayPairs.GetArrayElementAtIndex(index);
var unityEvent = element.FindPropertyRelative("unityEvent");
var delay = element.FindPropertyRelative("Delay");
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), delay);
rect.y += EditorGUIUtility.singleLineHeight;
EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUI.GetPropertyHeight(unityEvent)), unityEvent);
},
elementHeightCallback = index =>
{
var element = EventDelayPairs.GetArrayElementAtIndex(index);
var unityEvent = element.FindPropertyRelative("unityEvent");
var height = EditorGUI.GetPropertyHeight(unityEvent) + EditorGUIUtility.singleLineHeight;
return height;
}
};
}
public override void OnInspectorGUI()
{
DrawScriptField();
serializedObject.Update();
list.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
private void DrawScriptField()
{
// Disable editing
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField("Script", MonoScript.FromMonoBehaviour(_exampleScript), typeof(ExampleScript), false);
EditorGUI.EndDisabledGroup();
EditorGUILayout.Space();
}
}
Пример
или с предварительным просмотром задержек для отладки
public class ExampleScript : MonoBehaviour
{
public List<EventDelayPair> EventDelayPairs;
private void Start()
{
foreach (var eventDelayPair in EventDelayPairs)
{
StartCoroutine(InvokeDelayed(eventDelayPair));
}
}
private IEnumerator InvokeDelayed(EventDelayPair pair)
{
var timer = pair.Delay;
do
{
timer -= Time.deltaTime * (1 / Time.timeScale);
pair.Delay = timer;
yield return null;
} while (timer > 0);
pair.Delay = 0;
pair.unityEvent.Invoke();
}
[Serializable]
public class EventDelayPair
{
public UnityEvent unityEvent;
public float Delay;
}
}
Кстати, ваш комментарий
// Time.deltaTime будет увеличивать значение на 1 каждую секунду.
не сформулировано правильно.Вместо этого должно быть:
Time.deltaTime
будет увеличивать значение каждого кадра примерно на время, прошедшее в секундах с момента рендеринга последнего кадра.
РЕДАКТИРОВАТЬ - Уменьшить задержки впоследствии
Я понял из вопроса, что вы хотели speed up
всего воспроизведения.
Из комментариев, которые я узнал сейчас, вместо этого вы хотели скорее уменьшитьзадержка потом.Таким образом, вы не можете использовать Time.timescale
.
. Для этого вы можете использовать второй пример, слегка измененный:
[Serializable]
public class EventDelayPair
{
public UnityEvent unityEvent;
public float Delay;
// add a time multiplicator for each delay with default 1
public float TimeMultiplicator = 1.0f;
}
Примечание : вам придетсятакже добавьте его в EditorScript, если вы его используете - я оставляю это как домашнее задание;)
private IEnumerator InvokeDelayed(EventDelayPair pair)
{
var timer = pair.Delay;
do
{
timer -= Time.deltaTime * pair.TimeMultiplicator;
pair.Delay = timer;
yield return null;
} while (timer > 0);
pair.Delay = 0;
pair.unityEvent.Invoke();
}
, чтобы вы могли в Инспекторе или также по сценарию
exampleScriptReference.EventDelayPairs[0].TimeMultiplicator = 2;
уменьшить задержкубыстрее.
Вы также можете добавить общий мультипликатор, например
// Again you have to add it to the inspector if you use it
public float overallMultiplicator = 1.0f;
//...
timer -= Time.deltaTime * pair.TimeMultiplicator * overallMultiplicator;