- Home /
Reverse physics ?
Hey you guys,
I have an idea for a personal test project, in which I would like to throw rigidbodies (projectiles) at a wall or other rigidbodies and collapse it / move them with Physics, and then implement some kind of time reversal in which I would be able to build the wall anew in which the physics would play in reverse.
I really have no idea as to how to go about this in Unity. I do feel that storing, at every frame, each object's name, position and rotation in an array (or a list) would be crazy in terms of memory usage and processing power and would be absolutely inefficient. Plus, this would only be feasible for a limited amount of time, and not for the whole game (not that I absolutely want to do this for the WHOLE game, but it would be cool it if I could...)
I was wondering if the PhysX engine had some sort of reverse button, or if I would be able to implement that reversal through code (by, for example, using a negative force, if that is even possible -- even though the collision of two rigidbodies is not governed by a scripted force...)
I am at a loss here, so I would greatly appreciate any help from you learned folks here :-)
Thanks a bunch!
Ari ;o)
Answer by YoungDeveloper · Jun 13, 2016 at 07:18 PM
I suggest getting down at least some prototype, at least with couple objects, before optimizing it. Storing position and euler angles in a struct list seems like a good starting point to me.
edit: Note that i wouldnt mark the struct as serializable or serialize the list itself, to reduce possible bottleneck from unity editor inspector drawer.
Hey @YoungDeveloper, thank you for your answer :) Correct me if I'm wrong, but a struct cannot inherit from $$anonymous$$onoBehaviour (or from anything else, for that matter?), so how am I supposed to include such things as position (a Vector3) and rotation (a Quaternion) or eulerAngles (another Vector3)?
Plus I'm having a hard time figuring out what to do with the issue of time, frame after frame. Does this mean that I have to make a list of lists? (a list of all the objects' names, positions and rotations at time 0 + another for all the objects' names, positions, etc. at time 1, and so on, then all collected in a "list of lists" themselves ?)
Just create some Reversable Object
class, with List of Vector3s for positions and List of Quaternions for rotations(or another vector3s for euler angles). Then put something like positions.Add(transform.position); rotations.Add(transform.rotation)
in your Update, and it basically should do the work
You are over complicating things, you need the position and rotation, thats it, no names or inheritance. I slapped a quick example for you.
Demonstration: https://i.gyazo.com/aa24d4c7e2337519db918b8980749023.mp4
$$anonymous$$agic code:
public class $$anonymous$$agic : $$anonymous$$onoBehaviour {
[SerializeField]private Rigidbody _rigidbody;
private List<Node> _history = new List<Node>();
public bool record = true;
[Range(0f, 1f)]
public float lerp = 1f;
private struct Node {
public Node(Vector3 position, Vector3 eulerAngles) {
this.position = position;
this.eulerAngles = eulerAngles;
}
public readonly Vector3 position;
public readonly Vector3 eulerAngles;
}
public void Update() {
if(record) {
_rigidbody.is$$anonymous$$inematic = false;
_history.Add(new Node(transform.position, transform.eulerAngles));
}
else {
_rigidbody.is$$anonymous$$inematic = true;
int index = (int)((_history.Count-1)*lerp);
Node historyNode = _history[index];
transform.position = historyNode.position;
transform.eulerAngles = historyNode.eulerAngles;
}
}
}
Ins$$anonymous$$d of recording every frame id implement record ratio, which is basically how often we record per second. In update you would add time delta to some value, if its larger than that ratio then we write in a history node.
Answer by ahungrybear · Jun 14, 2016 at 06:05 AM
You don't have to store EVERY frame also. Depending on the complexity of the motion and how accurate you want the simulation, you could store the position and rotation every couple of frames and lerp in between them. That way you can store 3 or 4 times less data.
@ahungrybear: Thanks for the tip, that's actually a great idea!!
Answer by tanoshimi · Jun 14, 2016 at 05:49 AM
I've never used it, but for $40 this asset might seem a good investment for you:
@tanoshimi: This looks like a sweet asset indeed, but I'm not working on a proper game or anything. It was just a test project, sort of a little coding challenge for me. So the asset would kind of defeat the purpose, wouldn't it? :p Thank you, I'll keep the reference in $$anonymous$$d, though, if I need this for real, one day!
Assets aren't just for slapping in to finished games. I regularly acquire assets for the sole purpose of taking them apart and exa$$anonymous$$ing the source code to learn how a particular effect was achieved.
If they're well-structured and commented, you can treat them as interactive tutorials. For me personally, a one-off $40 seems like good value compared to the amount of time I'did otherwise spend trawling blogs or forums searching for tidbits of how to implement the same :)
Answer by MrYOLO · Jun 14, 2016 at 06:09 AM
hey there, from what I see you can just record every frame as a pic the just play them in reverse. It will gives players a feeling that the whole scene is reversing. The only con is you can not just rewind one object. The performance should be all right as it is just like playing video. hope it is clear with my poor English;)
@$$anonymous$$rYOLO: Your English is just perfect, don't you worry! Thanks for the idea, I must admit I hadn't even thought of it. I'd rather go down the road of recording data about the objects rather than still frames entirely, though, because I'd like some objects to be reversable and some not to be :)
Answer by Ari-Bouaniche · Jun 14, 2016 at 07:07 AM
So, after reading all of you guys' suggestions here, I decided to try my hand at implementing something. Right now I'm storing name, position and rotation @ every frame (I'll work on skipping frames and lerping later...), all into a giant "deported" list placed on an object.
Uh oh! While I'm typing this, I'm thinking this is awfully inefficient and I should save the data onto each object, not in a central list containing everything (which then has me looking for the gameObjects by name, which I read is a big no no...)
I'm going to try and assign a script to each object I want to reverse rather than centralize everything... More later! Thanks again to all of you who contribute to making those projects a little less lonely! :)
Your answer
Follow this Question
Related Questions
Problems making a glider 3 Answers
Raycast stops working after ~40 seconds when target has Rigidbody 2 Answers
Rigid body Help Please 1 Answer
Not all sides of a cube collide properly( with pic) 2 Answers
Character Controller meets Rigidbody 1 Answer