- Home /
How to record/save and replay/load a players' movement ?
How is such a behavior possible in Unity ? How can I use an array to save the position of the player and reload the same array to play when required ? Or is using a list a better thing than arrays ?
Consider this scenario. There are 3 objects - A, B and C. It is possible to control only 1 object at a time. Object A goes over some terrain and reaches a checkpoint, while B is waiting at the start. As A reaches the checkpoint, the movement is recorded and the game is restarted, with A now back at the start with B. Now, Object B has to go beyond the checkpoint, but this can happen, when the previously controlled Object A goes again to the checkpoint to unlock it, so that B can pass. Is it possible to save the movement of Object A in such a way, that it can be run again later ? This has to repeat for Object C again, so Object A and B now have to move as their movement was recorded, to help C cross the next checkpoint.
Thanks for reading the question and possibly providing a solution to it.
Answer by AlwaysSunny · Aug 31, 2014 at 09:59 PM
Interesting problem. Only the position of a given player A,B,C is important? There are no other actions which must be considered?
In that case, you could conceivably record the Vector3 position of each player in a list or array every N frames, then use some interpolation method to smooth between frames. Storing every single position of every frame is probably overkill, and doesn't sound wise.
The moment you include other factors besides position, this method falls apart. You'd then need to have every action the player takes fit into some object like PlayerAction, and store a list of those to play back instead.
Worth noting that you might ought to have an upper limit for your recorded movements and use a fixed length array. Resizing a very large list every N frames could create performance issues.
Also it occurs that your interpolation method for smoothing between recorded positions could probably be the same method you use to actually control the player, if you make your movement function "seek" a point rather than directly applying movement.
Answer by Kiwasi · Sep 01, 2014 at 12:38 AM
Another solution that I have kicked around in the past is to record the sequence of inputs a player makes. Then replay these inputs back to the controller. This is easy enough to do if you abstract your character controller to include an input module and an engine module.
There are some potential pitfalls to this approach if frame rate changes
Answer by iOSBoy · Apr 20, 2015 at 02:41 PM
//Im a bit late to this Convo but here is a solution for future comers, and the script is controlled by UI so you figure that out your self -
bool isRec = false;
bool doPlay = false;
List<float> nums = new List<float>();
List<float> instans = new List<float>();
float tempX;
float tempY;
float tempZ;
bool playedNoRep = false;
public Vector3 startPosi;
public GameObject Rob2;
public GameObject Rob3;
public GameObject Bullet;
// Use this for initialization
void Start () {
}
public void Record () {
if (isRec == true) {
isRec = false;
Rob2.GetComponent<Rob2Rec>().StopCoroutine("Playback");
Rob3.GetComponent<Rob3Rec>().StopCoroutine("Playback");
transform.position = startPosi;
GetComponent<Camera>().enabled = false;
}
else if (isRec == false) {
GetComponent<Camera>().enabled = true;
startPosi = transform.position;
isRec = true;
doPlay = false;
GetComponent<FirstPersonController>().enabled = true;
}
}
public void Play () {
GetComponent<Camera>().enabled = false;
GetComponent<FirstPersonController>().enabled = false;
}
// Update is called once per frame
public void Update () {
if (playedNoRep == true) {
doPlay = false;
}
if( isRec == true){
tempX = transform.position.x;
tempY = transform.position.y;
tempZ = transform.position.z;
nums.Add(tempX);
nums.Add(tempY);
nums.Add(tempZ);
}
if(doPlay == true){
doPlay = false;
StartCoroutine("Playback");
Debug.Log(doPlay);
}
}
public IEnumerator Playback ()
{
playedNoRep = true;
for (int i = 0; i < nums.Count; i+=3) {
transform.position = new Vector3 (nums [i], nums [i + 1], nums [i + 2]);
yield return null;
}
}
public void Reset () {
nums.Clear();
Application.LoadLevel("SciFi Level");
}
public void RunIt () {
isRec = false;
doPlay = true;
StartCoroutine("Playback");
}
public void showThisCam () {
if (doPlay = true) {
Rob3.GetComponent<Camera>().enabled = false;
Rob2.GetComponent<Camera>().enabled = false;
GetComponent<Camera>().enabled = true;
}
}
}
Thanks for the Script! I may be a bit late but i get an error when trying to use it.
Assets/Scripts/Record.cs: error CS0246: The type or namespace name List
1' could not be found. Are you missing a using directive or an assembly reference?
Any idea why is that happening?
@michaeldoukas This may be late, but I think you should add at the top of the script: Using System.Collections.Generic
Answer by Awss · Jun 14, 2015 at 03:09 AM
i am trying to solve this one too. But i think saving every frame is not so efficient, therefore my solution would be to store the player key input. For example let say player pressed right for 1 second record that, left for 2 second record that etc. on replay do the player actions which in turn will control your player. This way you save a lot less data. You also need to store the time between each key is idle, you can easily do this by reacting to events keyup and keydown. Hope it helps
Answer by $$anonymous$$ · Nov 02, 2015 at 07:24 AM
Thank you @iOSBoy!!
Wow- htat is awesome.
So, I was actually going to search a way to have frame-by-frame player position data and motions more exactly be dumped immediately into some kind of data-object externally in a file or an asset or maybe an RSS feed. Or to customise a pre-fab of another character! That might not be possible but htat's kind of what and how I would love to try.
So to begin, does anyone know how to take those position data and motions , and hten immediaely convert into a replay animation in another character? I mean, like automatically or stored somehow??
Your answer
![](https://koobas.hobune.stream/wayback/20220613162006im_/https://answers.unity.com/themes/thub/images/avi.jpg)