Search Unity

  1. The 2022.1 beta is now available for testing. To find out what's new, have a look at our 2022.1 beta blog post.
    Dismiss Notice

How to create ghost or after image on an animated sprite?

Discussion in '2D' started by ScratchModed, Jun 17, 2015.

  1. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Hey there.
    I am having an impossible time recreating this effect for my 2D platformer:


    I'd like to create a sprite trail just like in the example but I can't seem to figure it out; I can almost create the effect for just one still sprite with particles, but to have it trail after the sprite animations seems way out of my grasp. I've tried trail and line renderer but both those don't create a trail from the sprite sheet, only their own little separate effect.
     
    Last edited: Jun 17, 2015
  2. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Last edited: Jun 17, 2015
  3. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Ok, previous solution works for me fine, but not as good as I want, because it updates every trail part texture continuously.
    Here's another small example I've wrote for couple of minutes:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4.     void Start()
    5.     {
    6.         InvokeRepeating("SpawnTrail", 0, 0.2f); // replace 0.2f with needed repeatRate
    7.     }
    8.  
    9.     void SpawnTrail()
    10.     {
    11.         GameObject trailPart = new GameObject();
    12.         SpriteRenderer trailPartRenderer = trailPart.AddComponent<SpriteRenderer>();
    13.         trailPartRenderer.sprite = GetComponent<SpriteRenderer>().sprite;
    14.         trailPart.transform.position = transform.position;
    15.         Destroy(trailPart, 0.5f); // replace 0.5f with needed lifeTime
    16.  
    17.         StartCoroutine("FadeTrailPart", trailPartRenderer);
    18.     }
    19.  
    20.     IEnumerator FadeTrailPart(SpriteRenderer trailPartRenderer)
    21.     {
    22.         Color color = trailPartRenderer.color;
    23.         color.a -= 0.5f; // replace 0.5f with needed alpha decrement
    24.         trailPartRenderer.color = color;
    25.  
    26.         yield return new WaitForEndOfFrame();
    27.     }
    Add this code to your character's script on GameObject with Animator component.
    The code is pretty simple and works perfect for me. I wrote it in hurry, so it can be refactored and optimized:) For example you could reuse trailPart gameobjects instead of instantiating and destroying it everytime (object pool technique), etc., depends on you;)
     
    ScratchModed and BusyCat like this.
  4. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Well this is some pretty magnificent script you wrote for me; so pardon my while I show some cringe-worthy noobness.

    The ghost doesn't appear to be be affected by my Flip () function. so while it looks great heading in the correct direction. if i turn around my sprite the ghost doesn't turn as well :oops:
    Code (CSharp):
    1. void Flip ()
    2.     {
    3.         facingRight = !facingRight;
    4.         Vector3 theScale = transform.localScale;
    5.         theScale.x *= -1;
    6.         transform.localScale = theScale;
    7.     }
    Think you can help iron out this last wrinkle?
     
  5. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Ok, try this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3.  
    4. List<GameObject> trailParts = new List<GameObject>();
    5.  
    6. void Start()
    7. {
    8.     InvokeRepeating("SpawnTrailPart", 0, 0.2f); // replace 0.2f with needed repeatRate
    9. }
    10.  
    11. void SpawnTrailPart()
    12. {
    13.     GameObject trailPart = new GameObject();
    14.     SpriteRenderer trailPartRenderer = trailPart.AddComponent<SpriteRenderer>();
    15.     trailPartRenderer.sprite = GetComponent<SpriteRenderer>().sprite;
    16.     trailPart.transform.position = transform.position;
    17.     trailParts.Add(trailPart);
    18.  
    19.     StartCoroutine(FadeTrailPart(trailPartRenderer));
    20.     StartCoroutine(DestroyTrailPart(trailPart, 0.5f)); // replace 0.5f with needed lifeTime
    21. }
    22.  
    23. IEnumerator FadeTrailPart(SpriteRenderer trailPartRenderer)
    24. {
    25.     Color color = trailPartRenderer.color;
    26.     color.a -= 0.5f; // replace 0.5f with needed alpha decrement
    27.     trailPartRenderer.color = color;
    28.    
    29.     yield return new WaitForEndOfFrame();
    30. }
    31.  
    32. IEnumerator DestroyTrailPart(GameObject trailPart, float delay)
    33. {
    34.     yield return new WaitForSeconds(delay);
    35.  
    36.     trailParts.Remove(trailPart);
    37.     Destroy(trailPart);
    38. }
    39.  
    40. void Flip()
    41. {
    42.     facingRight = !facingRight;
    43.     Vector3 theScale = transform.localScale;
    44.     theScale.x *= -1;
    45.     transform.localScale = theScale;
    46.      
    47.     FlipTrail();
    48. }
    49.  
    50. void FlipTrail()
    51. {
    52.     foreach (GameObject trailPart in trailParts)
    53.     {
    54.         Vector3 trailPartLocalScale = trailPart.transform.localScale;
    55.         trailPartLocalScale.x *= -1;
    56.         trailPart.transform.localScale = trailPartLocalScale;
    57.     }
    58. }
    But I highly recommend you to use some kind of object pool system instead of new/Instantiate/Destroy calls:)
     
    BusyCat likes this.
  6. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Alright , updated the code to our new attempt but no luck. Seems like these ghosts just don't want to flip! Script still runs but acts unchanged.

    I will also haphazard this guess(which might be completely wrong since I know very little);
    The Hierarchy is instantiating the ghosts as "New Game Object", and I feel like maybe it's supposed to create them as trailPart for the "foreach" function to work.
     
    Last edited: Jun 20, 2015
  7. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Weird, it works perfect for my test project. Can you share your project?
     
  8. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    I'd be happy to share with you, if I knew how.
     
  9. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Hmm, upload it on dropbox or something and put the public link here
     
  10. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    [Link Disabled]

    Project called "character move tutorial without rigidbody" inside unity fails direcotry . I should probably rename it haha
     
    Last edited: Jun 20, 2015
  11. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Which scene should I open to test it?:)
     
  12. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    only have 1 scene called Level 1 haha
     
  13. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Weird, Level 1 scene is empty, did you save it?

    There are several scenes inside "ExampleScenes" folder:)
     
  14. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Unity Fails2\Character Move Tutorial without rigidbody\Assets\Levels
     
  15. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Yep, but there's nothing on this scene, there's no any object in the hierarchy
     
  16. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Wow that's wild- those examples are all part of A* pathfinding i think.

    Let me run a "save as" and see if I can send that over
     
  17. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    I promise these scenes aren't empty. They work on my second machine if I go into unity File>Open Project>Open Other>Character Move Tutorial Without Rigidbody>Select folder.

    Guess the whole project is required for the scenes inside it to work
     
  18. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    Oh, such a silly mistake!!!:)

    That's all you need:
    Code (CSharp):
    1. void Start()
    2. {
    3.     InvokeRepeating("SpawnTrailPart", 0, 0.2f); // replace 0.2f with needed repeatRate
    4. }
    5.  
    6. void SpawnTrailPart()
    7. {
    8.     GameObject trailPart = new GameObject();
    9.     SpriteRenderer trailPartRenderer = trailPart.AddComponent<SpriteRenderer>();
    10.     trailPartRenderer.sprite = GetComponent<SpriteRenderer>().sprite;
    11.     trailPart.transform.position = transform.position;
    12.     trailPart.transform.localScale = transform.localScale; // We forgot about this line!!!
    13.     trailParts.Add(trailPart);
    14.  
    15.     StartCoroutine(FadeTrailPart(trailPartRenderer));
    16.     Destroy(trailPart, 0.5f); // replace 0.5f with needed lifeTime
    17. }
    18.  
    19. IEnumerator FadeTrailPart(SpriteRenderer trailPartRenderer)
    20. {
    21.     Color color = trailPartRenderer.color;
    22.     color.a -= 0.5f; // replace 0.5f with needed alpha decrement
    23.     trailPartRenderer.color = color;
    24.  
    25.     yield return new WaitForEndOfFrame();
    26. }
    I completely forgot about trailPart.transform.localScale
    You don't need DestroyTrailPart and FlipTrail methods and you don't need List<GameObject> trailParts:)
     
    kishica likes this.
  19. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Oh that's much better, friend!
    I don't need this either, right?
    Code (CSharp):
    1.  
    2.  
    3. using System.Collections.Generic;
    4.  
    5. trailParts.Add(trailPart);
    Thank you so much!
    if you got another two seconds I'd be delighted to know how to change it's color as well?
     
    Last edited: Jun 21, 2015
  20. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    right.

    Code (CSharp):
    1. trailPartRenderer.color = Color.blue; // or new Color(0, 0, 255) or whatever you want
     
  21. ScratchModed

    ScratchModed

    Joined:
    Jun 5, 2015
    Posts:
    24
    Fantastic!
    I'll watch that Object pool technique later today and see if I can optimize this to your recommendation.
    I really appreciate it!
    Thanks so much.
     
  22. ANTARES_XXI

    ANTARES_XXI

    Joined:
    Dec 23, 2014
    Posts:
    141
    No problem!
     
  23. kishica

    kishica

    Joined:
    Jul 6, 2015
    Posts:
    2
    Good solution, but there is a way to make the ghost's scale "fading out" ?
     
    Last edited: Jul 6, 2015
unityunity