Hello, I made a deterministic replay system that store every player's input in a singleton.
It works but the replay is not always the same as the original.
Here is the code, it's no rocket science:
extends Node
enum State {STOP, RECORD, PLAY}
# h_ for history (we record in here)
var h_time := Array()
var h_inputs := Array()
var h_start: int
# r_ for replay (we read in here)
var r_time := Array()
var r_inputs := Array()
var r_start: int
var state
# keep track of pressed keys so we can release them manually at end
var pressed : Dictionary = {}
func _ready() -> void:
change_state(State.STOP)
func _input(event: InputEvent) -> void:
if state == State.RECORD:
h_time.append(OS.get_ticks_usec() - h_start)
h_inputs.append(event)
match event.get_class():
"InputEventKey":
pressed[event.scancode] = event.is_pressed()
func _physics_process(_delta: float) -> void:
if state == State.PLAY:
var ticks_usec = OS.get_ticks_usec() - r_start
while !r_time.empty() && r_time.front() <= ticks_usec:
r_time.pop_front()
Input.parse_input_event(r_inputs.pop_front())
func record():
seed(0)
change_state(State.RECORD)
h_inputs = Array()
h_time = Array()
h_start = OS.get_ticks_usec()
func stop():
change_state(State.STOP)
func play():
seed(0)
change_state(State.PLAY)
# start with everything released
# (or issue will rise when replay multiple times and player has a key pressed at end)
for scancode in pressed:
if pressed[scancode]:
var ev = InputEventKey.new()
ev.scancode = scancode
ev.physical_scancode = scancode
ev.pressed = false
Input.parse_input_event(ev)
# copy history in replay
r_start = OS.get_ticks_usec()
r_inputs = h_inputs.duplicate()
r_time = h_time.duplicate()
func change_state(enum_value):
print("[REPLAY] ", State.keys()[enum_value])
self.state = enum_value
func is_playing():
return self.state == State.PLAY
I do not have a single RNG in the game except for the camera which can shake a bit (I removed it and still have same issue).
Is there something obvious I missed? How would you have done it?