How can I compare transform.position now and transform.position after 2 seconds?
I'm making an endless runner and I want to restart the game if my player gets stuck for a short period of time.
Answer by Fire_Cube · Nov 02, 2015 at 05:09 PM
you can set an int(eg : framesFor2Secs) with a certain amount of frame to get 2 seconds (2 / Time.deltaTime), and check if the position is the same as the posiion last frame. if it is the case, just add 1 to an int counter, if not, put it back to 0. If the conter reach framesFor2Secs, player was stuck for 2 seconds.
Answer by Statement · Nov 02, 2015 at 06:51 PM
I guess you'd check if the players position has moved from a known point. If player ventures beyond the deadzone from that point, timer is reset. If timer reaches an expiry, restart the game.
Here's a set of component that provides base functionality and two example implementations. One of them takes care of loading the level directly. The other allows you to listen for event and can be set up in the inspector.
Each of the namespaces should go into a file with the same name as the class.
namespace ExampleImplementation
{
using Answers;
using UnityEngine;
[AddComponentMenu("Examples/Reload Level On Stuck")]
public class ReloadLevelOnStuck : ExpiryDeadzone
{
protected override void OnExpire()
{
print("Timer has expired. Reloading level.");
Application.LoadLevel(Application.loadedLevelName);
}
}
}
namespace ExampleImplementation
{
using Answers;
using UnityEngine;
using UnityEngine.Events;
[AddComponentMenu("Examples/Event On Stuck")]
public class EventOnStuck : ExpiryDeadzone
{
public UnityEvent onStuck;
protected override void OnExpire()
{
onStuck.Invoke();
}
}
}
namespace Answers
{
using UnityEngine;
public abstract class ExpiryDeadzone : MonoBehaviour
{
// Transform has to move 'deadzone.range' units to reset timer
[SerializeField]
private DeadZone deadzone;
// Timer waits 'expiry' seconds before invoking OnExpire
[SerializeField]
private ExpiryTimer timer;
// Allows OnExpire to be called multiple times
public bool resetOnExpire = false;
// Let user decide what happens on expiry.
protected abstract void OnExpire();
protected void Start()
{
ResetSystem();
}
protected void Update()
{
timer.Tick();
if (deadzone.IsOutOfRange(transform.position))
ResetSystem();
if (timer.isExpired)
{
if (resetOnExpire)
ResetSystem();
else
enabled = false;
OnExpire();
}
}
protected void ResetSystem()
{
enabled = true;
timer.Reset();
deadzone.pivot = transform.position;
}
}
}
namespace Answers
{
using System;
using UnityEngine;
[Serializable]
public class ExpiryTimer
{
public float expiry = 2;
public float elapsed { get; private set; }
public bool isExpired
{
get { return elapsed >= expiry; }
}
public void Tick()
{
elapsed += Time.deltaTime;
}
public void Reset()
{
elapsed = 0;
}
}
}
namespace Answers
{
using System;
using UnityEngine;
[Serializable]
public class DeadZone
{
public float range;
public Vector3 pivot;
public bool IsOutOfRange(Vector3 positon)
{
return Vector3.Distance(pivot, positon) > range;
}
}
}