C
C#16mo ago
anywhereiroa

❔ How to implement an "undo move" function in a game where I need to keep track of multiple objects?

PS: I'm using Unity by the way. tldr; In my game, every time the player moves one tile, different objects make different moves at the same time. How can I keep track of every single one and undo all of them one move back at the same time? I'm making a puzzle game where you move around in a grid-based space, i.e. like a checkerboard. The player character can move one tile at a time using the arrow keys. I want the player to be able to undo their moves if they make a mistake, get stuck etc. Now, if it were only for the player character, making an undo function is easy, I've already made it actually. I basically use the command pattern to record the character's position every time it moves, and add them to a Stack. When I want to undo, I just delete the last item on the stack and call the one before it. However, in my game, there is more stuff happening on different objects with each move of the player. For example, there are doors that open and close every time the player moves. There are also collapsing tiles which disappear after the player steps onto them and steps off. There are also special blocks which move the opposite way as the player i.e. if the player moves up, the block moves down, if the player moves right, the block moves left etc. So as you can see, I have a lot of elements that I need to keep track of, and there's also the case of the player "dying". Instead of having to restart the level all over, I would like to give the player the chance to undo just one mistake so that they can continue where they left off. But I don't know how to keep track of every element's behaviour every time the player moves, let alone how to undo them at the same time. I've heard about using .json files but I don't know if that would work or how I could implement that. I would appreciate any kind of help! Thank you very much!
6 Replies
Florian Voß
Florian Voß16mo ago
I don't know if this is a very modern or good approach to creating do, undo, and redo functionality but its the one I had learned when I was in school. I'd do Command Design pattern: Define a Command interface with Do, Undo, Redo methods. Now create different Commands that implement them, and whereever you wanna use the Commands you keep track of Stack<Command> to pop and push commands and to call Do, Undo, Or Redo on them depending on your logic afaik this is how the classic ctrl + z and ctrl + shift + z is implemented in most programs
anywhereiroa
anywhereiroaOP16mo ago
That's exactly what I did for the player. But my concern is, when I keep track of multiple objects, will they be added to the stack not simultaneously but rather consecutively, if that makes sense? So or example, when I move one tile with the player, these happen at the same time: - Player changes position - Door opens - Block moves in opposite direction So the stack would have each 3 as different items, therefore when I undo, first the block would move to its original place, then the door would close, then finally the player would move back. The only idea that comes to mind is to have EVERY SINGLE OBJECT that I want to undo inside the same command, however I imagine that getting pretty hectic.
Florian Voß
Florian Voß16mo ago
1.the items would be pushed and popped sequentially, with a LIFO (Last in first out) principle. If you need access from multiple threads to push and pop at same time for different players, you could use a ConcurrentStack<T> instead of Stack<T>. I don't know anything about gamedev but it probably makes much more sense to have one Stack<Command> or Stack<Movement> or whatever you wanna call it per player which reflects its turn that he can undo. In that case you don't need to access same stack from multiple threads 2. If you wanna undoo not single steps but whole Moves so to speak, that doesn't really change anything about the command design pattern, you just adjust what a Command or a Move really is. Your move can consist of 3 steps, could even use a Stack<Turn> where each turn consists of multiple moves, the pattern is very flexible @anywhereiroa sorry for late reply I was busy
anywhereiroa
anywhereiroaOP16mo ago
@voflorian99 Thank you very much for your detailed answer! I will try to figure something out, your replies actually allowed me to try to look at the problem from a different angle. Thank you again!
Florian Voß
Florian Voß16mo ago
glad I could help 🙂
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server