Last active
November 5, 2020 21:40
-
-
Save Marsgames/e6371b9e1e53d24e6eac2ed7e9b4c0bb to your computer and use it in GitHub Desktop.
A simple system to rewind time like in Prince of Persia
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source : https://www.twitch.tv/videos/519292916?filter=all&sort=time | |
#region Author | |
///////////////////////////////////////// | |
// RAPHAËL DAUMAS --> ICanRewind | |
// https://raphdaumas.wixsite.com/portfolio | |
// https://github.com/Marsgames | |
///////////////////////////////////////// | |
#endregion | |
public interface ICanRewind | |
{ | |
#region Unity's functions | |
#endregion Unity's functions | |
/////////////////////////////////////////////////////////// | |
#region Functions | |
void Rewind(); | |
void Record(); | |
#endregion Functions | |
/////////////////////////////////////////////////////////// | |
#region Accessors | |
#endregion Accessors | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#region Author | |
///////////////////////////////////////// | |
// RAPHAËL DAUMAS --> Player | |
// https://raphdaumas.wixsite.com/portfolio | |
// https://github.com/Marsgames | |
///////////////////////////////////////// | |
#endregion | |
using UnityEngine; | |
using System.Collections.Generic; | |
[RequireComponent(typeof(Rigidbody2D))] | |
public class Player : MonoBehaviour, ICanRewind | |
{ | |
#region Variables | |
[SerializeField] private float jumpVelocity = 5; | |
[SerializeField] private float fallOffMultiplier = 2.5f; | |
[SerializeField] private float lowJumpMultiplier = 2; | |
private Rigidbody2D rigidbody; | |
private Stack<Instant> instants = new Stack<Instant>(); | |
#endregion Variables | |
/////////////////////////////////////////////////////////// | |
#region Unity's functions | |
private void Start() | |
{ | |
TimeManager.Instance.SetRewindable(this); | |
rigidbody = GetComponent<Rigidbody2D>(); | |
} | |
private void Update() | |
{ | |
Move(); | |
} | |
#endregion Unity's functions | |
/////////////////////////////////////////////////////////// | |
#region Functions | |
private void Move() | |
{ | |
if (Input.GetKey(KeyCode.Q)) | |
{ | |
transform.position += Vector3.left * .1f; | |
} | |
if (Input.GetKey(KeyCode.D)) | |
{ | |
transform.position += Vector3.right * .1f; | |
} | |
Jump(KeyCode.Space); | |
} | |
/// <summary> | |
/// Function to jump like in Mario (long press jumps higher than short press) | |
/// </summary> | |
/// <param name="jumpButton">Jump button.</param> | |
private void Jump(KeyCode jumpButton) | |
{ | |
if (Input.GetKeyDown(jumpButton)) | |
{ | |
rigidbody.velocity = Vector2.up * jumpVelocity; | |
} | |
if (rigidbody.velocity.y < 0) | |
{ | |
rigidbody.velocity += Vector2.up * (Physics2D.gravity.y * rigidbody.gravityScale) * (fallOffMultiplier - 1) * Time.deltaTime; | |
} | |
else if (rigidbody.velocity.y > 0 && !Input.GetKey(jumpButton)) | |
{ | |
rigidbody.velocity += Vector2.up * (Physics2D.gravity.y * rigidbody.gravityScale) * (lowJumpMultiplier - 1) * Time.deltaTime; | |
} | |
} | |
/// <summary> | |
/// Set the value back to rewind time | |
/// </summary> | |
public void Rewind() | |
{ | |
Instant t; | |
if (instants.Count > 1) | |
{ | |
// Pop remove element from stack when we use it | |
t = instants.Pop(); | |
} | |
else | |
{ | |
// Peek only get element | |
t = instants.Peek(); | |
} | |
transform.position = t.GetPosition(); | |
rigidbody.velocity = t.GetVelocity(); | |
} | |
/// <summary> | |
/// Save everything we want to save for the player | |
/// </summary> | |
public void Record() | |
{ | |
Instant t = new Instant(transform.position, rigidbody.velocity); | |
instants.Push(t); | |
} | |
#endregion Functions | |
/////////////////////////////////////////////////////////// | |
#region Accessors | |
#endregion Accessors | |
#region Struct | |
/// <summary> | |
/// Structure that will contains all informations we wants to record for this class | |
/// </summary> | |
struct Instant | |
{ | |
private Vector2 instantPosition; | |
private Vector2 instantVelocity; | |
public Instant(Vector2 position, Vector2 velocity) | |
{ | |
instantPosition = position; | |
instantVelocity = velocity; | |
} | |
public Vector2 GetPosition() | |
{ | |
return instantPosition; | |
} | |
public Vector2 GetVelocity() | |
{ | |
return instantVelocity; | |
} | |
} | |
#endregion Struct | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source : https://www.twitch.tv/videos/519292916?filter=all&sort=time | |
#region Author | |
///////////////////////////////////////// | |
// RAPHAËL DAUMAS --> TimeManager | |
// https://raphdaumas.wixsite.com/portfolio | |
// https://github.com/Marsgames | |
///////////////////////////////////////// | |
#endregion | |
using System.Collections.Generic; | |
using UnityEngine; | |
public class TimeManager : MonoBehaviour | |
{ | |
#region Variables | |
[HideInInspector] public static TimeManager Instance { get; private set; } | |
private bool isRewinding; | |
private List<ICanRewind> rewindables = new List<ICanRewind>(); | |
#endregion Variables | |
/////////////////////////////////////////////////////////// | |
#region Unity's functions | |
private void Awake() | |
{ | |
if (!Instance) | |
{ | |
Instance = this; | |
} | |
else if (this != Instance) | |
{ | |
Destroy(gameObject); | |
} | |
DontDestroyOnLoad(this); | |
} | |
private void Update() | |
{ | |
RewindButton(KeyCode.S); | |
} | |
/// <summary> | |
/// Record/Rewind time when isRewinding is true | |
/// Maybe it should be dirrectly into RewindButton function ? | |
/// </summary> | |
private void FixedUpdate() | |
{ | |
foreach (ICanRewind obj in rewindables) | |
{ | |
if (isRewinding) | |
{ | |
obj.Rewind(); | |
} | |
else | |
{ | |
obj.Record(); | |
} | |
} | |
} | |
#endregion Unity's functions | |
/////////////////////////////////////////////////////////// | |
#region Functions | |
/// <summary> | |
/// Set isRewinding when rewindButton is pressed | |
/// </summary> | |
/// <param name="rewindButton">Rewind button.</param> | |
private void RewindButton(KeyCode rewindButton) | |
{ | |
if (Input.GetKeyDown(rewindButton)) | |
{ | |
isRewinding = true; | |
} | |
else if (Input.GetKeyUp(rewindButton)) | |
{ | |
isRewinding = false; | |
} | |
} | |
#endregion Functions | |
/////////////////////////////////////////////////////////// | |
#region Accessors | |
/// <summary> | |
/// Used for objects implementing ICanRewind to call there Record/Rewind functions | |
/// </summary> | |
/// <param name="obj">Object.</param> | |
public void SetRewindable(ICanRewind obj) | |
{ | |
rewindables.Add(obj); | |
} | |
#endregion Accessors | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment