Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by erikiene · Nov 17, 2016 at 03:35 PM · scripting problemtimearraysrewind

Rewind time (or problems with arrays)

Hi all,

I'm implementing a mechanic where when triggered, target objects would rewind to their initial positions/rotations/etc. The problematic part of this currently looks something like:

     ArrayList Movements = new ArrayList();
     ArrayList Rotations = new ArrayList();
     public GameObject[] targets;
 
 (in update when not rewinding:)
 
             for (int i = targets.Length-1; i >= 0 ; i--)
             {
                 Movements.Add(targets[i].transform.position);
                 Rotations.Add(targets[i].transform.rotation);
             }
 
 (coroutine to rewind when trigerred:)
 
             for(int i = 0; i<targets.Length; i++)
             {
                 targets[i].transform.position = (Vector3)Movements[MovementIndex];
                 Movements.RemoveAt(MovementIndex);
                 targets[i].transform.rotation = (Quaternion)Rotations[MovementIndex];
                 Rotations.RemoveAt(MovementIndex);
             }
             yield return new WaitForSeconds(0f);
 

I think I've pasted in all the relevant parts for solving what's wrong. Basically, it worked well for just one target, e.g. player, but I want to implement an open array defined in the editor (GameObject[] targets) so I can apply the rewind to any object I want. So when I went and tried it with a player and the camera, it, for some reason (possibly my lack of understand how these arrays are called), it looks like the camera jumps around as if it's using all of the positions and rotations recorded, not just the ones captured from the camera transform. I played around with order of execution in the "for" functions but to no avail..

Any ideas?

Additionally, if anyone has a suggestion on how to implement the captured parameters in a single multi-dimensional array, please share, I couldn't wrap my head around that either. Something like [(player.position1, player.rotation1),(cam.pos1, cam.rot1),....] but that'd be there just to make it neat so is not as important.

ALSO, optimization related advice would be most welcome as well. I.e. storing all of these states will be expensive if a player takes a while going through a level and I can't really delete any of the stored data as I want everything to come back to the point when the level started. I guess storing every other frame would do, but then how would I smoothly transition across two states without it looking like glitchy teleportation?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by roman_sedition · Nov 17, 2016 at 06:08 PM

@erikiene OMG This was a lot of fun trying to figure this out.

I made 2 scripts, it sort of allows you allocate which objects you want to have rewind via AddComponent, this lets each object have their own position and rotation list so you don't have some gigantic multidimensional array to worry about. Clears the list after a rewind occurs. This example will allocate which objects will be able to rewind during Start(), but it's pretty easy to implement dynamically during gameplay too.

First Script (placed on an empty object in the scene, just used for allocating which objects get to rewind, you retain a reference to each object in this Object's targets List)

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine.UI;
 
 
 public class TimeController : MonoBehaviour {
 
 
     public List<Vector3> targetPos = new List<Vector3>();
     public List<Quaternion> targetRotate = new List<Quaternion>();
     public GameObject[] targets;
 
 
     void Start()
     {
         targets = GameObject.FindGameObjectsWithTag ("Target");
 
         foreach(GameObject target in targets)
         {
             target.AddComponent<Rewinder> ();
         }
 
     } 
 
 
 }


Second Script (This one gives the Rewind class to the object, I made RigidBody a required component, may or may not want to implement that depending on your game)

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine.UI;
 
 [RequireComponent(typeof(Rigidbody))]
 public class Rewinder : MonoBehaviour {
 
 
     public List<Vector3> targetPos = new List<Vector3>();
     public List<Quaternion> targetRotate = new List<Quaternion>();
     public bool record;
     
 
     void Start()
     {
         record = true;
 
     } 
 
 
     void Update()
     {
 
         if(record)
         {
             targetPos.Add (transform.position);
             targetRotate.Add (transform.rotation);
 
         }
 
 
         if (Input.GetKeyDown (KeyCode.Space) && record == true)
         {
             StartCoroutine ("Rewind");
         }
             
 
     }
 
     IEnumerator Rewind()
     {
         record = false;
         GetComponent<Rigidbody> ().isKinematic = true;
         for(int i = targetPos.Count - 1; i > -1; i--)
         {
             transform.position = targetPos [i];
             transform.rotation = targetRotate [i];
 
             yield return null;
         }
 
         GetComponent<Rigidbody> ().isKinematic = false;
         targetPos.Clear ();
         targetRotate.Clear ();
         record = true;
         yield return new WaitForSeconds(0);
     }
 
 
 
 }

I put yield return null in the for loop of the coroutine as it makes rewind playback frame by frame the same as it was recorded. If you are rewinding to a state in which you were airborne at the start you need kinematic set to true, then revert it when it is finished or else the acceleration of gravity whilst you're airborne is still in effect and it makes the object fall faster when rewind finishes.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image erikiene · Nov 18, 2016 at 01:00 PM 0
Share

@roman_sedition it really is fun! Thank You for all of this, the whole of the 2 scripts look similar to what I have, I'll try the whole thing out and if it works as I want it to (which by the looks of it it will) I think I can squeeze both Your scripts into one, will let You know if it's working!

I haven't tried using Lists ins$$anonymous$$d of ArrayLists, which seems easier with them having .Add and .Clear. Also, the is$$anonymous$$inematic tip is great because for some reason ins$$anonymous$$d of doing that I turned my custom gravity on and off each time..

Now, this might be a stretch but any chance You would have ideas on how to implement animations into this whole mechanic? I'm sure I can work it out eventually but doesn't hurt to ask a person who seems to know his stuff!

EDIT: After taking a closer look at what the first script does and implementing that (never used addcomponent in such a way before) I see there's not really a way to combine them into one but there's no reason to anyway, what You have works perfectly! All I need now is to figure out how to add animations to the rewind.

Thanks once again!!

avatar image roman_sedition erikiene · Nov 18, 2016 at 01:28 PM 1
Share

@erikiene You are welcome, about animations, no I don't think I can help you there. Logic wise it should be similar, I am guessing you would somehow store key frame references of the animations and play them back in reverse order.$$anonymous$$y current hobby is just lurking on unity.answers trying to raise reputation points and gain badges like it was a game lol I am definitely not that knowledgeable.

avatar image erikiene roman_sedition · Nov 22, 2016 at 12:30 PM 0
Share

:D well, I can say that's a wonderful hobby to have and thank you on behalf everyone you've helped and will help in the future!

Sorry to come back to this but I just had one more problem related to it all and thought maybe You'd be able to help me.

I'm trying to slow down the rewinding at certain points (triggered by colliders) but Time.timeScale won't work on the coroutine and simply waitforseconds'ing will make it look like choppy teleportation rather than slowed down rewinding. I'm trying to implement this with vector3 and quaternion.Lerp (and move/rotateTowards) but can't seem to get my head around what t I should use and how many seconds to wait for between the calls.. When I tried using one time for the lerp/movetoward and then wait for that exact amount of seconds before looping again, the target ends up floating, moving through ground, etc...

I'm still sitting down thinking about the logic behind this but as before - doesn't hurt asking.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Character controller without Deltatime 1 Answer

Increase speed over time 0 Answers

Spawning enemies based on array of times 0 Answers

I want to make the gameobject rigidbody.iskinematic=true for 3s and immune to damage when it triggers the collider and then false again 0 Answers

Jagged Array returns null anywhere outside function that populates it 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges