Time travel in Unity | Useless Game Dev

Time travel in Unity | Useless Game Dev

Useless Game Dev

3 месяца назад

23,658 Просмотров

Ссылки и html тэги не поддерживаются


Комментарии:

@notTryio
@notTryio - 19.01.2024 21:04

Mayonnaise on an escalator

Ответить
@zaj007
@zaj007 - 19.01.2024 21:16

How's your indie game coming along?

Ответить
@draakevil
@draakevil - 19.01.2024 21:20

Awesome video. Very easy to understand the concept.

Ответить
@beidero
@beidero - 19.01.2024 21:41

I do wonder if a linked list would be a good method for storing the recorded frames, since you would always start at the last frame and jump backwards. Search would always be 0(log(n)) but you get to skip the conversion to array or list which would save quite some time on larger lists. You could even do like a secondary list that stores references to every 100 recorded frames or so, so you can skip backwards quickly if needed and then just start your search from the closest frame to the frame you are looking for.

Ответить
@TobyJWalter
@TobyJWalter - 19.01.2024 23:10

I love your videos, keep up the amazing work! ♥

Ответить
@jorgellorca7232
@jorgellorca7232 - 19.01.2024 23:50

I worked in a game for a game jam last week and one of the mechanics was time travel. We implemented a much easier system, as we only had to modify time in one scene with a set length of one minute, and we just used timeline for doing it. But watching your video has motivated me to take this approach in future projects that have this kind of mechanics. Also, as an engineer, I really enjoyed the optimization you did on the recorder algorithm. Congrats!

Ответить
@slice6298
@slice6298 - 20.01.2024 00:13

Great idea, yet relatively simple to implement
Really shows that you don't need to be incredible at programming to be able to create games with fun systems

Ответить
@dantelaviero7782
@dantelaviero7782 - 20.01.2024 00:28

he coded a vegan robot

Ответить
@xeetsh
@xeetsh - 20.01.2024 00:52

Great video! Especially great that you showed how to optimize this. Most tutorials are lacking this step.
I made a game jam game once that used basically the same technique, not for rewinding, but for playing certain actions back. Your goal was to catapult a car to a certain point with conveyors, explosives and oil spills by placing those objects, seeing where the car would land, resetting the car and continuing to build your track from there. As Unity physics are far from deterministic, I needed a way to record what happened before the reset in order for the car to land where it landed last time. Not the best thing to have to deal with during a three-day game jam, but I managed to do it basically exactly how you managed to record and rewind movement of game objects in your video (just way less performant)!
The game is Wildlife Camping Experiences (on itch) if anyone is interested :)

Ответить
@williefr
@williefr - 20.01.2024 02:13

What an awesome video! I love when we can optimize stuff. I also learned a time ago these algorithms and just forgot them as I'm not using them at work. Also very well explained and a lot of work put in. New subscriber 😊

Ответить
@BobsMudHut
@BobsMudHut - 20.01.2024 02:55

Great video! I've been working on a game with time manipulation for over a year and still use lists to store all my rapidly changing data (like transform positions) because I haven't gotten around to optimizing everything yet 😅. For things that don't change very often or on many objects like changing animations or interactions between timed objects I use a linked list that records forwards/backwards functions with any needed state parameters to save on space. Writing the functions can be a little complicated sometimes but it means I can record any arbitrary action I want and it doesn't have to be dependent on constantly storing/checking state every frame like when recording transform positions. When things get really fun (read: complicated) is when you have different objects rewinding/replaying at different speeds/directions in time.

Ответить
@AxeLea3
@AxeLea3 - 20.01.2024 03:30

An interesting game that is centered around time travel is Prince of Persia: the sands of time
Everything is time travel in that game. Story, movement and combat all implement it

Ответить
@alex2416
@alex2416 - 20.01.2024 03:36

i always wondered how they made this work on a Switch for TOTK. Thanks for exploring this question, great video ! :D <3

Ответить
@RevymOfficial
@RevymOfficial - 20.01.2024 03:37

Your design also shows the potential for in-game replays. Great Work!😄

Ответить
@omayoperations8423
@omayoperations8423 - 20.01.2024 04:05

There's a great VR game that does something like this. It's called "The Last Clockwinder"

Ответить
@jjrubes1880
@jjrubes1880 - 20.01.2024 04:35

How did you implement binary search? I can't think of how it would be possible if you've got gaps in the list without some indication of the nearest change

Ответить
@RGHdrizzle
@RGHdrizzle - 20.01.2024 05:51

I was just planning to implement a time rewind system as a small project and here u go with an upload exactly about that which also gave me some insights on how to do it

Ответить
@newe6000
@newe6000 - 20.01.2024 07:04

I'm surprised nobody has mentioned how this approach naively assumes that a frame is a fixed length of time, instead of being dynamic. To be fair it works much better than I expected in this prototype, but once you put this in a more complicated scene with framerate fluctuations they're going to start showing up in the recordings.

A more ideal solution I think would record at a fixed framerate (maybe every second fixed update?) then interpolate between those frames on playback. Though I understand avoiding that complexity in a first draft prototype.

Ответить
@anonymous49125
@anonymous49125 - 20.01.2024 07:25

converting the keys to array or list also means you're allocating a new array each time you do that... which your GC is going to have a field day and will likely cause a huge lag hickup every 1 second.... with thousands of objects doing this every frame --- wew lad...

I'm glad with the bst optimization you were able to cut the times down - and if it works, it works - but the approach I would use is having all the recorders be subscribers, recording not to a dictionary but a fixed size array (a list that keeps keyframe for each rendered frame forever is too wild for my blood), and then going back in time, just ask each subscriber if they have something to do for the current frame (a rolling index to keep track of what your current saved keyframe is); if they have nothing going on and are just waiting around then they can check if the last recorded key (that current frame index again) matches the current time or not, if it does, then go back one more keyframe in the array and figure out the distance of time between the current and the previous keyframe - and use that for interpolating between those two keyframes- then when asked if they are busy or not next time (which they are busy interpolating), then interpolate between those two keyframes instead. If you ask them to do something and they don't have anything for this frame and they are not interpolating between frames, then do nothing. this takes your O(log n) - where N are all your keyframes in the tree for that object and brings it down to O(1), just asking "do something for this frame" to each object. I think the benefits are not just performance (where there assuredly would be - doing a bst per frame per object is bananas - and in any case O(log n)>O(1)) but more important, readability. Mucking about with dictionary is nice for that key lookup of O(1) but any type of figuring out where the last keyframe is, makes it a less than optimal strategy.

Ответить
@jokesterthemighty227
@jokesterthemighty227 - 20.01.2024 09:14

That's not how it's typically done, see with rollback network solution you already store a lot of previous frames so it's trivial to make them play backwards (in an offline setting)

Ответить
@awesomemike3857
@awesomemike3857 - 20.01.2024 10:52

Why do all of this when you can just set Time.timescale = -1 lol

Ответить
@MattyDoesGameDev
@MattyDoesGameDev - 20.01.2024 11:01

I'm imagining how exponentially more complicated this can get when you include objects that change states, for example a barrel that explodes! You'd have to design each gameplay object to have time-travel in mind. Thanks for the fun video, as always!

Ответить
@alejo460
@alejo460 - 20.01.2024 13:30

Useless game dev but every single video is the most useful and talented game dev video possible

Ответить
@DarthBiomech
@DarthBiomech - 20.01.2024 15:25

I had an idea about space strategy game that takes light speed into account and forces the player to play predictively, so this will definitely be useful, thanks!

Ответить
@DarthBiomech
@DarthBiomech - 20.01.2024 15:43

One question though, why is your solution was generic <T> instead of a simple inheritance? at least in the video, I don't think any of the script examples seem to utilize <T>.

Ответить
@designator7402
@designator7402 - 20.01.2024 16:15

A little while ago I saw a video about cursed units of measurement, and I think I will add "Frames per Frame" to my own personal list of cursed measurements. Thanks, funny blue turtle friend.

Ответить
@0hellow797
@0hellow797 - 20.01.2024 17:06

How impossible would it be to implement a replay system that can fit on any game. I don’t want to think about it anyway lmao

Ответить
@steluste
@steluste - 21.01.2024 00:48

What's the name of your visual studio theme?

Ответить
@KansasToYou
@KansasToYou - 21.01.2024 08:44

Awesome video man. Great work

Ответить
@bungercolumbus
@bungercolumbus - 21.01.2024 10:46

Wouldn't time.timescale = 0 be a better approach for pausing the game?

Ответить
@reguret2976
@reguret2976 - 21.01.2024 13:08

boids!

Ответить
@edwardperkins1225
@edwardperkins1225 - 21.01.2024 14:05

I wonder if Nintendo will actual try suing people for time rewind mechanics in non-Nintendo games considering the US patient office was stupid enough to give them one for it in TotK. Maybe it only counts if you use a cursor to select what to rewind.

Ответить
@ibrabdo
@ibrabdo - 21.01.2024 14:16

Great video :D Interesting idea, i'll try to apply the same concept in unreal engine for my game 😅

Ответить
@MarekNijaki
@MarekNijaki - 21.01.2024 16:42

Great video

Ответить
@AdamMelvins
@AdamMelvins - 21.01.2024 22:29

Awesome video! :) I'd like to note that your "simple scene" is utterly beautiful! :) I love that art style, the distance fade - it looks gorgeous and makes for a really nice video to watch. :)

I've been working on a "replay system" for work, and thankfully it's not got anything with physics, just player positions, the task/quest, and what's on the UI and the positions/visibility of objects. Even that... took a LOT of work :) You're a wizardly wizard, and that's a really clean implementation! Thank you for making something near and dear. :)

Ответить
@PingsGolf
@PingsGolf - 22.01.2024 08:14

This was a nice video. Well made and interesting topic
Also i like the music👍

Ответить
@omnisel
@omnisel - 22.01.2024 08:41

Binary searches are so cool !!! Always the best way to search an arbitrarily large ordered list.

Ответить
@Queue_Bert
@Queue_Bert - 22.01.2024 19:10

My Team is actually working on a 3D puzzle platformer about time travel right now! I'm the animator, not the lead programmer, but from what I can tell your implementation of rewinding and recording is similar to ours but a fair bit more complex and versatile. We're mainly recording the player's position rotation velocity, and then playing it back as "clones" the player can then interact with. For at least my animations I wish we could go back and rework the systems to take advantage of some of the ideas you brought up in your video here, but I'm not sure how possible it's gonna be this late in development 🫠. Either way, this was a great video as always, keep up the amazing work!!

Ответить
@PantheraLeo04
@PantheraLeo04 - 23.01.2024 07:08

You may have mentioned this and I just missed it, but if you're already recording velocity each frame, wouldn't recording position be redundant. If you have a starting position (the moment you begin rewinding time) and the velocity at each point in time, I'm pretty sure you should be able to just derive the position from those right? And the same would be true of the rotation and angular velocity.

Ответить
@s1lkysl1m83
@s1lkysl1m83 - 23.01.2024 08:29

unity, LOL!

Ответить
@JamesTM
@JamesTM - 24.01.2024 17:53

Really cool video, as always! Very interesting.

One possible, significant optimization you could consider:
For the rewind/ff, I dont think you need to access an arbitrary frame. You only need to acces the frame either immediately before or immediately after the "current" (last recorded/restored) frame. Or at least within a very small number of frames, if you're skipping some. But never thousands of records backwards in the list. So, perhaps a doubly-linked list would be the most efficient data structure. That way, you can scrub backwards and forewards through the list without worrying about arbitrary lookups.

In theory, that would also make deleting "future" frames as easy as deleting the forward link from the current frame record. (I say "in theory" because I don't know anything about Unity's garbage collection.)

Ответить
@ladiesman2048
@ladiesman2048 - 25.01.2024 06:19

Iron Danger is a Unity game that has time rewind mechanic

Ответить
@amarok8bit
@amarok8bit - 26.01.2024 21:43

What a great video! I also like games with time manipulation like Braid. Last year I wrote my game Time Wizard for Atari 8-bit computer. You can see it on my channel. I fully understand problems related to memory management for storing and restoring gameplay. In my case I had 48kB of RAM and CPU with 1.77 MHz. So this is completely different environment but the same challenges. Thanks for sharing. :)

Ответить
@Draugo
@Draugo - 28.01.2024 17:25

Personally instead of gaps I would have recorded changed values as a new index and then had a frame array where each frame has the value of the current latest recorded values. Sure you're adding an int to the recorded data but you don't need to deal with gaps and the correct data is easily findable with frame index. For purge you could remake the frame array until the desired spot and then discard all frame data that is higher than the stored index of the last frame.

Ответить
@DrEnzyme
@DrEnzyme - 30.01.2024 01:11

It's amazing how easily you can get cool mechanics out of a system like this when you have the base implementation. You can have objects that are immune to time travel just by deleting their recorders. The objects that lose momentum when they're unfrozen in time can be a game mechanic. You can have multiple copies of your player that appear every time loop, leading to fun interactions and paradoxes.

Time travel is sick.

Ответить
@sambo3975
@sambo3975 - 30.01.2024 21:43

Just set timescale to -1, dummy!

Ответить
@Conman9310
@Conman9310 - 05.02.2024 12:43

couldnt you store the frame number when adding to the record and just use that number to find the most recently added one instead of a search

Ответить
@morgan0
@morgan0 - 03.03.2024 10:56

i think you could get a further speed increase by storing all parameters for one object in one frame, since most of the time they’d all change together. it might also be worth looking back at the last second recorded, and replacing some frames with a smaller amount of interpolation frames, which could store less data and be simpler to lookup.

Ответить
@oglothenerd
@oglothenerd - 04.03.2024 21:34

Have you considered switching to Godot?

Ответить
@mmertduman
@mmertduman - 30.03.2024 15:17

You could also set a fixed time delta for when you record the state! Most of your values are interpolable, and given a small enough time delta, a linear interpolation wouldn't look bad. So instead of saving 60 states per second (or whatever your fps is), just save 5 or 10 and lerp between them.

Ответить