Moongate Games UK

"Changing worlds, one line of code at a time"

Tutorial: Ghosts #3 - Playing a recorded ghost.

Introduction:

In this part of the tutorial we'll be making a script that we can attach to an object and get it to move in accordance to the list of snapshots provided.

Playing:

First things first, we need to create a new script called GhostPlayer.cs and add both of the following namespaces:

using System.Collections.Generic;
using Ghosts;

nce you have added those two, within the GhostPlayer class you will need to add the following variables:

private List<Snapshot> _snapshots;
private bool _started = false;
private float _time;

nce you have added those three variables your code should look like the following:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Ghosts;

public class GhostPlayer : MonoBehaciour {
    private List<Snapshot> _snapshots;
    private bool _stated = false;
    private float _time;
    
    //Use this for initialization
    void Start(){
    
    }
    
    //Update is called once per frame
    void Update(){
    
    }
}

ext we'll be adding the functions to:

  1. Load a list of snapshots to  the GhostPlayer script and set it off.
  2. Check that we actually have more than no snapshots to run our ghost.
  3. Have a check to make sure that the snapshot in the 0 index position is the correct time, then move the object and set it's rotation, then remove the snapshot at the 0 index.

To do all of this we'll need to code the following functions:

public void LoadGhostAndStart(List<Snapshot> snapshots){
    _snapshots = snapshots;
    if(_snapshots.Count > 0){
        _started = true;
        transform.position = Vector3.zero;
    }
}

bool IsThereSomethingToGhost(){
    if(_snapshots.Count > 0)
        return true;
        
    _started = false;
    return false;
}

void UpdateGhostPosition(){
    if(_time >= _snapshots[0].Time){
        transform.position = new Vector3(_snapshots[0].XLocation,_snapshots[0].YLocation,_snapshots[0].ZLocation);
        transform.rotation = new Quaternion(_snapshots[0].XRotation,_snapshots[0].YRotation,_snapshots[0].ZRotation,_snapshots[0].WRotation);
        _snapshots.RemoveAt(0);
    }
}

Notice that there are a few things different in the above code. Firstly we need to have the function that loads the ghost as public for when we need to load it from outside the class. Secondly we require a return statement when check if there is anything to ghost.

Lastly we'll need to initialise the Snapshot list and make it work. So for that we'd need to add some code to both the Start()  and Update() functions.

void Start(){
    _snapshots = new List<Snapshot>();
}

void Update(){
    if(_started){
        _time += Time.deltaTime;
        
        if(IsThereSomethingToGhost())
            UpdateGhostPosition();
    }
}

After all that you should have the following code to attach to the object you want to use as the ghost.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Ghosts;

public class GhostPlayer : MonoBehaciour {
    private List<Snapshot> _snapshots;
    private bool _stated = false;
    private float _time;
    
    //Use this for initialization
    void Start(){
        _snapshots = new List<Snapshot>();
    }
    
    //Update is called once per frame
    void Update(){
        if(_started){
            _time += Time.deltaTime;
        
            if(IsThereSomethingToGhost())
                UpdateGhostPosition();
        }
    }
    
    public void LoadGhostAndStart(List<Snapshot> snapshots){
        _snapshots = snapshots;
        if(_snapshots.Count > 0){
            _started = true;
            transform.position = Vector3.zero;
        }
    }

    bool IsThereSomethingToGhost(){
        if(_snapshots.Count > 0)
            return true;
        
        _started = false;
        return false;
    }

    void UpdateGhostPosition(){
        if(_time >= _snapshots[0].Time){
            transform.position = new Vector3(_snapshots[0].XLocation,_snapshots[0].YLocation,_snapshots[0].ZLocation);
            transform.rotation = new Quaternion(_snapshots[0].XRotation,_snapshots[0].YRotation,_snapshots[0].ZRotation,_snapshots[0].WRotation);
            _snapshots.RemoveAt(0);
        }
    }
}

That's it, that's all the code needed for a basic Ghost system. Doing it this was makes it look kind of laggy (as you can see from the video below.) Some implementing something like lerping from one position to the next would make it much smoother.

And that is that for this tutorial.

Although since I've hit 1K followers on Twitter today, this weekend I'll be writing up a blog post on the different applications for this kind of system. So keep an eye out for that and I hope you enjoyed the tutorial. Feedback and Comments are very much welcome.

Bonus Part (Coming Soon) -->