Unity3d rollback to previous state? - unity3d

I am looking for a way to make my Unity3D application able to "rollback" to a previous state so that the scene is exactly the same as it was N milliseconds.
For example, say I have a player which has moved forward 5 units. There are objects in the foreground moving around, such as a ball rolling... now imagine that I would like to "undo" 3 moves: the player should appear where he was 3 steps ago and the rolling ball should also move backwards in time.
What approach would I take here? I have thought to create "states", each timestamped with Time.realTimeSinceStartup, but that property is readonly. Alternatively, I thought that I could keep track of frame count, enable V-Synch so that render time is at 30ms, and rollback 30ms * n_frames, but unfortunately, the render time is not constant, even with V-Synch.
Perhaps this is similar to saving the game and then restoring it? However, the save and restore need to be very fast, on the order of less than 10ms.
What are my options here?

Related

Is there a way to run a separate Update at a faster rate than the Application.targetFrameRate?

I am looking to poll Unity inputs over the last several frames and use that data to interpret the user's button presses. From what I've tested however, it feels like polling at the application's 60 FPS framerate leads to some very fast inputs getting missed.
Simple example, user tries to go to Forward from Down:
frame 1 - user is holding Down
frame 1.5 - user taps Forward, but hasn't released Down yet
frame 2 - user lets go of Down and has reached Forward fully
In my current set up, using unity's framerate update, frame 1.5 where the user has both Down and Forward held is missed entirely. Is there a way to run a separate update, that runs at a faster rate than the regular Unity MonoBehaviour Update function? Or would a different solution be needed, such as querying via events(iirc that's an option, but I may be misremembering)?
I don't believe it's possible to decouple polling frequency from frame rate in legacy input system, however in new input system there is a pollingFrequency property that allows you define the frequency in Hertz. It uses a background thread to poll the data. You also need to subscribe to an input action change and record your values there to finally consume them in update method.

How to change the index of a ConcatenatingAudioSource?

I am using ConcatenatingAudioSource in order to play multiple tracks without gaps like this :
player.setAudioSource(ConcatenatingAudioSource(children: [
///some audio sources
]));
If I want now to change the next track to be played, intto a track at an index specified by me, how to do that other than keeping calling player.seekToNext() ?
Is there for example some method like player.setNextTrackIndex(someIndex) ?
p.s. : This question is about just_audio package.
The closest thing to what you're trying to do is:
await player.seek(Duration.zero, trackIndex);
This immediately starts buffering the requested track in order to play it, but there will still be a gap initially while you wait for the audio of that track to buffer. It will be a short gap if the media is stored locally, and a longer gap if the media is accessed over a network.
This is distinct from actual gapless playback which can only happen when the player knows ahead of time which track is next so that it can start buffering it early and avoid the gap. That is, if the user can choose a track at any time, there is no way for the player to predict in advance which track the user will click on next.
Yes, ConcatenatingAudioSource is designed to do gapless playback, but between items that it know are coming next. It is intended to concatenate tracks A,B,C,D together so that there is no gap between A-B, between B-C and between C-D. It can do this because when the player is reaching the end of track A, it knows that B is coming up next and starts buffering B early. Gapless playback doesn't apply to your scenario.

GameKit turn timeout

GameKit allow us to end a turn with a timeout for the next participant in the match. However, I couldn't find a way to set a timeout for the first participant for its first move. Is there anyway to do that?
EDIT
It started to make sense to me why Apple would leave this out from GameKit. When you just join a GKTurnBasedMatch you will always be in turn so there's no need for a timeout considering that it was added to avoid frustration on players while waiting too long for their turn. The thing is that my use case for a timeout is different. I'm designing a tournament and a timeout means that you lost the match, no matter it's the first turn or not. So I always need to have the ability to timeout the current turn. I'm afraid I'll need to implement this on the server which just sucks.
Might be a little late on this one, but Game Center TBM timeouts don't work like that.
When you call endTurnWithNextParticipants you must provide a list of players that will receive the turn if the previous one times out. If you want a player to lose the game when he/she times out, you must implement this e.g. on the client of the next player that receives the turn, Apple serves won't do this for you.
Based on what you're aiming for, I think the best implementation would be to check for the time the latest turn was played, or the match creation time in case it's the first turn, compare it to the current system date and time and programmatically end the match if time is over.
Like you point out, as player1 on turn1, there aren't any other players yet, so I suspect that's why GC doesn't give us an interface to set the timeout for player1.
How about setting an NSTimer to the desired timeout, and then ending the turn when it fires?
If you're looking at a long timeout, say a few days, where the user might leave and then rejoin after the timeout, you could calculate the desired deadline by adding the timeout interval to the match start time, and store that in NSUserDefaults. On each game startup, check if the deadline has passed, and end the turn when appropriate.

Changes in data after game was inactive

I'm starting to work on an app similar to tamagotchi (virtual pet kind of stuff) in the Corona SDK. I got absolutely stuck and am out of ideas on how to get one part.
How can the game character, lets say "pet" change its status, e.g. become hungry or die while the game is inactive? Or maybe its possible to make the changes as the player enters the game the next time, maybe to bind it to the global time (still no idea of how to do it)?
I would appreciate any help.
The simplest I can think is to keep all relevant data in a file. The first datum would be a time stamp of the last time the game was turned inactive.
Every time the game is first activated it reads the file along with the time stamp. After a specific time length has passed the pet becomes hungry, tired, etc. If an extraordinary long time has passed the pet dies.
You can go further by putting a time stamp next to each datum like "last fed", "last watered", etc. and then you can make individual attributes expire at different times, including death by boredom by keeping the global "last active" time and if a long time has passed without running the game the pet dies.
I actually created an application like this. I created a number of states in a enum and then in a checkMoodState method I hardcoded the values that decided the state of the mood.
e.g.
timeSinceLastPlay
timeSinceLastFeed
or whatever.
Either write the dates to a plist for each variable you want to track and on each check or store them in NSUserDefaults(one function to write them all, one to load them all), subtract the current time from it. You will be left with a negative number, and you can just get its absolute value.
You decide whenever you want to check the last time since whatever it is you are checking, e.g. feeding. Create an NSTimer with the duration of the time between checks and in the method called by the timer, you do you checks and update the mood as you need.

iPhone "multi-threading" question

I have a simple iPhone game consisting of two "threads": the main game loop where all updating and rendering happen 30 times per second (NSTimer)... and the "thread" that calls the accelerometer delegate 100 times per second. I have a variable "xPosition" that's updated in the accelerometer delegate function and used in the game loop. Is there a possibility of the two "threads" trying to use xPosition at the same time (hence causing a crash or some other problem). If so how can I fix this w/ minimal impact to the game's performance?
I've been using this set-up for many months of development and incremental testing and I've never run into any problems.
Cheers!
If your NSTimer task and your game loop are both run from the main thread you will not encounter any problems with this since only one of them will execute at the same time. Additionally none of them can preempt the other.
However if you are using different threads, you have to be careful when using the xPosition in the game loop since it's value might be updated at any time from the other thread - even though there is only one processor. One simple way of getting past this would be to assign the value of xPosition to a local variable in the game loop and only reference this variable for each run through the loop.
If it's only updated in the accelerometer thread, then there's not much problem. Worst case is that the render thread won't see the change to the data by the accelerometer thread. Since you're running on a single processor, that's not likely to happen. That latter problem can be addressed if you flag the variable as 'volatile' in the source code.