Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Make Ghost Replay Smoother

Discussion in 'Scripting' started by NightLucididty, Jan 23, 2016.

?

Is this code efficient? If not could you please state why

  1. Yes

    1 vote(s)
    100.0%
  2. No

    0 vote(s)
    0.0%
  1. NightLucididty

    NightLucididty

    Joined:
    Jun 12, 2015
    Posts:
    4
    I have created a sort of ghost replay for my 2D platformer, I did this by storing the positions, getting the times... But the problem is that the replay is smooth, when I do not play with the original player,
    But as soon as I start moving the player it looks like the ghost is lagging (I guess we can call it lagging).

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class GhostPlayer : MonoBehaviour {
    6.    
    7.     public List<Vector2> playerMove;
    8.     public List<float> timedMove;
    9.     public List<float> animX;
    10.     public List<float> animY;
    11.     public List<bool> isGrounded;
    12.     public List<bool> wallTouch;
    13.  
    14.     public GameObject MySpriteOBJ;
    15.    
    16.     Vector3 MySpriteOriginalScale;
    17.  
    18.     Vector2 GetPlayerMove(int index) {
    19.         if (index < playerMove.Count) {
    20.             return playerMove[index];
    21.         }
    22.         else {
    23.             return Vector2.zero;
    24.         }
    25.         return Vector2.zero;
    26.     }
    27.  
    28.     PlayerMovementScript original;
    29.  
    30.     float startTime;
    31.     float journeyLength;
    32.    
    33.     Animator animations;
    34.    
    35.     public int numberOfMoves = 0;
    36.  
    37.     void Start () {
    38.         var go = GameObject.FindGameObjectWithTag ("Player");
    39.         original = go.GetComponent<PlayerMovementScript> ();
    40.  
    41.         MySpriteOriginalScale = MySpriteOBJ.transform.localScale;
    42.  
    43.         animations = MySpriteOBJ.GetComponent<Animator> ();
    44.  
    45.         playerMove = new List<Vector2>(original.playerPos);
    46.         timedMove = new List<float> (original.timedPos);
    47.         animX = new List<float> (original.animX);
    48.         animY = new List<float> (original.animY);
    49.         isGrounded = new List<bool> (original.isGrounded);
    50.         wallTouch = new List<bool> (original.wallTouch);
    51.  
    52.         startTime = timedMove [0];
    53.  
    54.         original.playerPos.Clear ();
    55.         original.timedPos.Clear ();
    56.         original.animX.Clear ();
    57.         original.animY.Clear ();
    58.         original.isGrounded.Clear ();
    59.         original.wallTouch.Clear ();
    60.     }
    61.  
    62.     void Update() {
    63.         if(GetPlayerMove(numberOfMoves+2) != Vector2.zero) {
    64.             journeyLength = Vector3.Distance(transform.position, playerMove [numberOfMoves+1]);
    65.             float distCovered = (timedMove [numberOfMoves+1] - startTime);
    66.             float fracJourney = distCovered / journeyLength;
    67.             transform.position = Vector3.Lerp(transform.position, playerMove [numberOfMoves+1], fracJourney);
    68.            
    69.             animations.SetBool ("Grounded", isGrounded [numberOfMoves + 1]);
    70.             animations.SetBool ("Walled", wallTouch [numberOfMoves + 1]);
    71.             animations.SetFloat ("HorizontalSpeed", animX[numberOfMoves+1]);
    72.             animations.SetFloat ("VerticalSpeed", animY[numberOfMoves+1]);
    73.            
    74.             if (transform.position.x == playerMove [numberOfMoves+1].x && transform.position.y == playerMove [numberOfMoves+1].y) {
    75.                 numberOfMoves++;
    76.             }
    77.            
    78.             if(transform.position.x < playerMove [numberOfMoves+1].x) {
    79.                 MySpriteOBJ.transform.localScale = MySpriteOriginalScale;
    80.             } else if(transform.position.x > playerMove [numberOfMoves+1].x) {
    81.                 MySpriteOBJ.transform.localScale = new Vector3(-MySpriteOriginalScale.x,MySpriteOriginalScale.y,MySpriteOriginalScale.z);
    82.             }
    83.         }
    84.  
    85.         if(original.deadPlayer == true) {
    86.             foreach(GameObject ghostPlayers in GameObject.FindGameObjectsWithTag("GhostPlayer")) {
    87.                 original.deadPlayer = false;
    88.                 ghostPlayers.transform.position = original.ActiveCheckpoint.transform.position;
    89.                 ghostPlayers.GetComponent<GhostPlayer>().numberOfMoves = 0;
    90.             }
    91.         }
    92.     }
    93. }
    Any idea on what might be causing the issue?
     
  2. Ian094

    Ian094

    Joined:
    Jun 20, 2013
    Posts:
    1,548
    It could possibly be your camera. Do you follow the player in Fixed or Late update?
     
  3. Fajlworks

    Fajlworks

    Joined:
    Sep 8, 2014
    Posts:
    344
    Is it possible that when you use Ghost along with Player playing:
    Code (CSharp):
    1. var go = GameObject.FindGameObjectWithTag ("Player");
    2. original = go.GetComponent<PlayerMovementScript> ();
    3.  
    that the supposedly saved variables are overwritten by your actual Player input? It is a hunch, because you are referencing in both cases to your Player gameObject, fetched with "Player". Maybe instead tag "Player" you meant "GhostPlayer", like the one at the bottom of your Update() method?
     
  4. NightLucididty

    NightLucididty

    Joined:
    Jun 12, 2015
    Posts:
    4
    I follow the player in fixed update, That is the most efficient way to do camera follows isn't it?
    Thanks for the quick reply
    NightLucidity
     
    Last edited: Jan 24, 2016
  5. NightLucididty

    NightLucididty

    Joined:
    Jun 12, 2015
    Posts:
    4
    No its completely normal, I am first storing the value in the player movement script, and than clearing them, (This is so that I can have multiple ghosts on the screen at once). And than whenever the player dies, the values are sent to each GhostPlayer. The reason why I am referencing the actual player is just so that I can clear the values, saving them for the next ghost.

    I am looking for an effect like this game that was posted in ludum dare #26 Mustache Armies. Any Ideas of a better way I could have implemented the effect? Because I just noticed that my speed is actually slower than the actual players, and this is really frustrating me...
    Thanks for the quick reply
    NightLucidity
     
  6. Ian094

    Ian094

    Joined:
    Jun 20, 2013
    Posts:
    1,548
    Yeah, if the transform has a rigidbody.

    Does your ghost have a rigidbody? If so, set gravity to off, make it kinematic and playback using Rigidbody.MovePosition

    This might fix the lagging for you.

    Record in FixedUpdate() and playback in FixedUpdate(). This way it'll playback at the same speed that it was recorded.

    I hope you resolve it soon.
     
    NightLucididty likes this.
  7. NightLucididty

    NightLucididty

    Joined:
    Jun 12, 2015
    Posts:
    4
    Thanks a bunch this seems to solve the issue,
    NightLucidity