Originally I planned to put it in Design, but it feels too “code-y” for there, but at the same time it feels too vague for Scripting. The solution? General Discussion! Below is my thread text
So… where does this thread go?
Also any help with the subject itself would be great.
You’ll have hard time with this one and might hit a wall.
To implement something like this, for every second you need to record position, orientation, animation frame and animation speed. Basically, for every value you record, you need to record value and its rate of change, and acceleration of said rate of change. Then you should be able to recreate scene easily.
However. As far as I know unity animation system based on animation controllers is completely unsuitable for this task. You cannot rewind clips and play transitions backwards.
So you’ll either need to implement completely custom animation solution for everything or you could try unreal 4, which does have a tool for that, called “animation montage”. There were games that used that tool for reversing time… not for 24 hour period though.
The realistic solution would be to record position and direction of movement for every npc (“schedule”), and then based on a time of day determine in which direction they face, and in which direction they move. That way you’ll be able to reconstruct similar scene every time, but it won’t be 100% identical every time you visit specific time spot.
You may be able to create duplicate actions in animation controller (“forward/backward” version of every action), but still, you’re going to have a lot of trouble with this problem in unity.
Could you manage your own time for each level or section of the game, then have that be used in every calculation of position and so on. So say you wanted to go back 6 hours, you could enter in some time 6 hours ago and the game would be able to calculate where everything should be and what it should be doing at that time? An example would be a person will move left at time 2:57 and you can just go back to 2:58 and that person will have moved left.
This is a really vague description but it seems to be a way of doing it that doesn’t involve recording everything. (I have no idea really how you would implement this still)
[Edit] Realised this probably wouldn’t work if you needed to take into account player interactions with NPCs
The thread belongs in scripting. Design is for working out the details of how a system should work. You seem to have done that. Implementation is for the scripting forum.
On the actual topic, you need to work on shifting your system from an incremental step based one to a deterministic time based one. This is pretty easy for simple systems, but can be rough for more complex ones.
Of the solutions you presented, the animation curve system seemed the best to me. Set up your simulation in the normal way. Then run it through with a recorder pumping all of the key data to animation curves trend.Me might work. Then push the curve back into you simulation at runtime.
If the game has any complexity, this will border on impossible to accomplish.
You need very top quality code to even consider it, since it really needs to be precise and deterministic. The way you write everything, from AI to animation to position, etc, all of this needs to be written extremely deliberately.
You can’t do any kind of interpolation, since this will prevent accurate deterministic results. So if you want this to be correct, curves are out. If the idea is to sort of fudge stuff to fake it in presentation, maybe. But if you need to be able to reproduce results accurately, this needs to be some very extreme code, and it would not be for the squeamish. Rewriting the animation system would probably be a second tier challenge at that point.
I’ll take a swing at simply throwing out an idea that may or may not be plausible.
That’d be 172,800 floats over 24 hours. Ouch.
I think a good thing to at least attempt would be mathematical modeling. Every ten minutes take the current position of the entity. Then poll it’s velocity every second.
When X(10 from now on) number of minutes elapses, have a thread create a model for the data using some form of curve fitting(probably best to check out Normal or Cauchy distribution). This is sloooooww. However, we won’t really care. This is a prime candidate(and easy use case) for aggressive threading in both the algorithm itself and to enclose the algorithm. Once this process finishes, simply delete the original polling data and store the model.
When a request comes to roll back time (t), we take the initial position from that time sector(10 minutes chunk) and then do a simple trapezoidal approximation of the position at time, t, based off of our velocity model. There are a ton of different ways to optimize this depending on how lossy of a algorithm is acceptable.
There are some glaring issues with this; modeling is pretty slow the closer to reality you need, so for real-time needs it will be a lossy playback state. It’s not a big deal that modeling is slow, since we will have our polling to use in case a playback is requested before the algorithm finishes.
Would love to see if this is applicable with today’s technologies. It has the major benefit of having a constant complexity in respect to time. Overtime, it will not bog down with massive data, as polling would.
Edit: you’ll still hit the other issues with animation and etc. as described above. This might only solve positioning and velocity.
General Discussion is never the answer for anything technical. It’s strictly for stuff like “Unity vs [other game engine]”, “What do you think about game dev”, etc.
This is a very interesting idea. I think if I wanted to achieve this I would approach it at a higher level such as only recording the event points. By that I mean only the times that actually started something happening / changed a behavior. Such as an AI deciding to move in a certain direction at certain speed or moving to a certain position or whatever.
Basically only looking at the key points in time that resulted in changes in the game world over the following seconds. In a way you could see it like key frames in an animation sequence. Which I think is basically the kind of thing you are considering. Not sure because the “animation curve” thing I don’t get. Not into that stuff enough to know what it is even is. lol
Anyway, whenever a decision is made that will alter the behavior that is what is recorded. Recording position, angle facing, the new state of the object and other related parameters. Then these could be replayed back at any point. When looking at any point in time you’d need to move backward to find the last event / key that occurred before that point in time. And that needs to be done for every object. Then you simply do a super fast forward update forward in time from that key time to the desired time. I mean just let the game run. Think of it as everything has been restored to the point of that last key frame.
That is just off the top of my head. Not saying it would be flawless. Possibly I’d look into building some kind of compression system for this as well depending on just how many key points of data need to be stored.
So reading this thread and experimenting gave me a basic idea of what to do.
Essentially, I have to write my own special recorder/playback system based on animation curves. Each object will have its velocity tracked and a keyframe will be placed on each velocity change. This… isn’t the most efficient system though as it means things like turning corners will have just absolutely massive keyframe dumps. I’ll probably have to implement a special resolution system to prevent things from getting out of hand. It’s actually ridiculously easy to handle this sort of thing with animation playback scripts:
The real tricky part is going to be handling poses. For each animation, I’m going to have to have a separate, reversed animation to properly handle blending. I can automate this too, but it’ll be a considerably lengthier process since I have no idea where to start with that. Maybe there’s a way to make blender animations automagically play backwards? Who knows.
Still, this seems infinitely more possible than it did the other day, so thanks for all the tips!