This is a prototype game I made for my capstone at UTD. The premise is: you're stuck in a run-down factory, and you need to use time travel to solve puzzles using previous versions of yourself. I had the idea for this game ~2 years ago, and I got a small start on it at the time. I left it alone it until August 2020, when I chose it to be my capstone project.
I was inspired by amazing puzzle games like Portal and The Talos Principle. The latter even features time travel puzzles of its own, but I wanted to put my own unique spin on them. Instead of using your previous self to solve and immediate problem, the goal of Temporal Assembly Line is to create an infinite time loop that fulfills a particular task forever.
If I had more time, I would want to create more interesting puzzle designs and better graphics. Ultimately, I'm very happy with this game as a base for future expansion, and someday I'd love to come back to it. I think it's a great showcase of many of the techniques and skills I've learned from my time at UTD.
Below you can find a button that you can use to download and play the game yourself (Windows only), along with a video playthrough of the game
Temporal Assembly Line was featured as part of UTD's Fall 2020 ATEC Capstone Celebration. Click the button below to see the projects of other Fall 2020 graduates!
To force the player to prove that they haven't solved the puzzle by accident, puzzle rooms are separated by locked doors that only open after a sufficient number of time loops are successfully completed. I got the idea for this from Zachtronics, who makes games where the player has to design their own robust solutions.
Time travel is, of course, the central mechanic. I probably spent the most time trying to get it working the way I wanted, and there were many different paths I took. I wanted the system to be as modular as possible, so the player has several components: PlayerController, MovemenetController, and GrabController. PlayerController is the only script that interfaces with the user, and it feeds data into the other two. But it also broadcasts inputs to an action, and the MovementRecorder script remembers these inputs and stores them in a list. It then spawns copies of the player and replaces the PlayerController component on them with an ArtificalController that is designed to send stored player inputs to its own MovementController and GrabController.
At first, the clones moved purely based on the force values recorded from the player. However, it quickly became clear that their positions would diverge from where they were supposed to be. I knew the best way to avoid this would be to simply have the clones advance to the recorded position of the player at each frame, but I also knew that this would potentially create some strange actions, especially if the player jumped on a box that could move later. I elected for a compromise, where the clones follow the player's position values at first, but if the player tries to jump and the clone is unable to, then it becomes "desynced" and begins to use the force values instead.