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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Replay player movements (like zombie tsunami)

Discussion in '2D' started by paul_evc7, Aug 27, 2016.

  1. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I want to know how to make an script with a behavior like the game zombie tsunami, when you pick another object (in my case dogs), it will follow you but it's not an enemy it's a friend. I don't know if I can explain what I want to do. The difference with another chasing scripts that I found it is that the movement it's delayed to replay player movements. Its a 2d platform game and you can freely move around.
     
    Last edited: Aug 30, 2016
  2. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    So do you want this friend (dog,whatever) to exactly move how the player moved just delayed? Or can the dog just run directly to the player from whereever he is?
     
  3. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    the dog can run to the player's position but the problem is when you have more dogs, the second dog needs to follow the first dog, the third needs to follow the second and etc. That's why I said its like the game zombie tsunami, if you can see all the zombies jump but not a the same time.
     

    Attached Files:

  4. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Well you could make a prefab of a dog with a DogController Script added to it. (so every dog you instantiate will have it attached). Then inside the script do someting like this:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DogHandler : MonoBehaviour {
    5.  
    6.     private float timer;
    7.     private int actionID;  // action we need to take.  if actionID = -1 no action is pending.
    8.  
    9.     // Update is called once per frame
    10.     void Update () {
    11.         if (actionID == -1)
    12.             return;
    13.         else
    14.             timer -= Time.deltaTime;
    15.         if (timer < 0)
    16.             PerformAction();
    17.     }
    18.  
    19.     private void PerformAction()
    20.     {
    21.         timer = 0;
    22.         switch (actionID)
    23.         {
    24.             case 0:
    25.                 // Do whatever action  0 is
    26.                 break;
    27.             case 1:
    28.                 // do whatever action 1 is
    29.                 break;
    30.         }
    31.         actionID = -1
    32.     }
    33.  
    34.     public void SetAction(int id, float timer)
    35.     {
    36.         actionID = id;
    37.         this.timer = timer;
    38.     }
    39. }
    Then your Main game code would call it like this (say jump action was ID = 1)
    dogObject1.SetAction(1,0.5f);
    dogObject2.SetAction(1,1.0f);
    dogObject3.SetAction(1,1.5f);
    And so on...
    Starting in 1/2 second dog 1 will start jumping.. then each 1/2 second after that the rest start jumping

    You could even change it from just 2 simple variables time/actionID.. and put those into a struct. Then you could have a List of those structs and queue up actions

    The Normal running could be handled by starting them X distance behidn the player.. then whenever you move him , move every dog the same amount forward. The jump action would just be a new Update() item that slowly moved their Z position up and down over time. You would start it using the SetAction I showed above.
     
  5. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I will check that thanks I'm kind of new writing scripts (sorry I replied from my phone but it seems the reply didn't post)
     
  6. jamius19

    jamius19

    Joined:
    Mar 30, 2015
    Posts:
    96
    So if I understood correctly, you want some object to follow you when you pick up?
     
  7. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    This is a basic prototype for a chain of following objects. Objects that do the following have the "MoveTowardObject" script, and can follow the player by calling the player's "AddFollower" function. Each follower will follow the last in the chain.

    I did not test this.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4.  
    5. public class Player : MonoBehaviour
    6. {
    7.     private List<MoveTowardsObject> followers = new List<MoveTowardsObject>();
    8.  
    9.     public void AddFollower(MoveTowardsObject follower)
    10.     {
    11.         if(followers.Count > 0)
    12.         {
    13.             // new followers follow the last in the list
    14.             follower.target = followers.Last().transform;
    15.         }
    16.         else
    17.         {
    18.             // first follower follows the player
    19.             follower.target = transform;
    20.         }
    21.         followers.Add(follower);
    22.     }
    23.  
    24.    
    25.     public void RemoveFollower(MoveTowardsObject follower)
    26.     {
    27.         // find the follower that is moving towards the one to be removed
    28.         MoveTowardsObject needsNewTarget = followers.Find(f => f.target == follower.transform);
    29.  
    30.         // give that follower the target of the one to be removed
    31.         needsNewTarget.target = follower.target;
    32.  
    33.         // remove the follower
    34.         followers.Remove(follower);
    35.     }
    36. }
    37.  
    38. public class MoveTowardsObject : MonoBehaviour
    39. {
    40.     public Transform target;
    41.  
    42.     // set in inspector
    43.     public float followSpeed;
    44.     public float stopDistance;
    45.  
    46.     private void Update()
    47.     {
    48.         if(target != null && Vector3.Distance(transform.position, target.position) > stopDistance)
    49.         {
    50.             transform.position = Vector3.MoveTowards(transform.position, target.position, followSpeed);
    51.         }
    52.     }
    53. }
     
    Last edited: Aug 29, 2016
  8. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    Yes, that's exactly that I want to do
     
  9. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I will try it as soon as I can thanks
     
  10. jamius19

    jamius19

    Joined:
    Mar 30, 2015
    Posts:
    96
    Why not just use a pathfinding?
    It'd a whole lot easier and the following objects will follow you..... well... intelligently ;)
     
  11. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I tried the script but the object that follows the player just teleports, I don't know if I'm doing something wrong
     
  12. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Thats because @jeffreyschoch code is just instantly setting the transforms to a new position.
    Instead of just setting their position, You would need to gradually change their position from their current to the position you want it to be. A CoRoutine is perfect for this:
    https://docs.unity3d.com/Manual/Coroutines.html
     
  13. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    But does it work the same in a platform 2d game?
     
  14. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    So I just replace the transform with a coroutines?
     
  15. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    I wasn't familair with zombie tsunami so I went and watched a video of it. I noticed there wasn't a paticular "player" you just controlled the horde. Though the lead zombie was the one that would act first. If a whole slew of zombies in the front died, then whichever one was left in the front would be come the new "lead" zombie. Is this how your game will work. Or do you have a specific main player, and he just has followers behind him.

    Secondly, and the code for movement must logically flow from this question. How is the game setup. Is this a sidescroller like zombie tsunami? Or is your player able to move around in a 2d world?
     
  16. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I have an specific main player I just want other characters follow him and yes I forgot to say that its a 2d platform game and you are able to move freely around en the 2d world.
     
  17. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    That makes it more complicated than zombie tsunami. SInce I assume you don't ever want all the follower piled on top of you they have to delay a bit., you have to worry about cases where you player is near the edge of the screen. He successfully jump up to a platform then moves right and causes the entire screen to scroll (assuming the level he's on is bigger than one screeen). now the zombie that has to jump can't use his exact positions he used since he'll hit the platform. Or if your platforming scrolls up and down followers can be left off screen.

    I'll have to think about it. But i think the implmentation will greatly depend on how your platformor works. Does the screen slide around if the charcter moves too near the edges.. Can it scroll up/down. I assume you will have objects that the player can jump up onto. but could also bounce against if he tried to jump from underneath it, or missed the jump.
    Can the player start jumping right and then move left to slow his jump movement like Super Mario brothers?

    Finally. In zombie tsunami the zombie horde *IS* the player. Your implementation would greatly depend on what are those followers? What is their purpose in the game .. why do I have them?
     
  18. jamius19

    jamius19

    Joined:
    Mar 30, 2015
    Posts:
    96
    Nope!
    In the case of a 2D game use the A* Pathfinder Project on assetstore.
    It's free!
     
  19. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Will A* pathfinder handle things like jumping. I thought that was more for negotiating a flat plane that had obstacles?
     
  20. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    Yeah... I think it's more complicated that it sounds, but in summary, its a 2d platform game and the camera follows the main player, the player can jump freely in platforms (more like mario bros) so... I will try A* pathfinder I hope that solves the jumping action problem and now the other big problem for me its when yo pick a dog, it will follow you at the end of the line of dogs. I'm thinking to put just 5 dogs per level but I don't really know how to do that for now.
     
  21. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    Do you know how to use it on a 2d platform game?
     
  22. jamius19

    jamius19

    Joined:
    Mar 30, 2015
    Posts:
    96
    I haven't used it, but seeing from its documentation it should be fairly simple.

    Check it here!

    They also seems to cover the topic of how to make something follow the player!
    Think it'd be enough to lighten up your mind! :D
     
  23. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802

    This is not correct. I'm using MoveTowards in an update which is a gradual interpolation between points at a max speed of "followSpeed".

    You probably did not set a proper follow speed in the inspector.

    Follow distance takes care of the pile-up, as they will only follow until within a certain radius.

    Using the method I described, you can use that follower chain to save and relay actions to the whole chain. You can have them follow with a delay, and it's expandable to do any kind of ghosting. Every follower knows what it's following, and can mimic the behavior as you see fit at a delay.

    Alternatively you can save player data at a certain interval in an array and then play it back in the followers once the player moves far enough.
     
    Last edited: Aug 30, 2016
    jamius19 likes this.
  24. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    I set the follow speed between 0.01 to 0.03 but the object just slide (the animations don't work) and when I jump the object that has the MoveTowards script jumps constantly in the same place.
     
  25. paul_evc7

    paul_evc7

    Joined:
    Aug 27, 2016
    Posts:
    13
    Ok... I have a new idea, I just want to know how to make a delay between the controls and the character reaction, example:
    -> I press the right arrow on the keyboard.
    -> The player moves 0.5 seconds later.

    I tried with an yield return new WaitForSeconds(millis); but it doesn't work.
     
  26. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Have a separate function that moves your player (sets his tranform whatever). If this function is called MovePlayer() then you use Invoke

    Invoke("MovePlayer",0.5);
    Note: invoke just takes a string name of the method, so you can't really pass arguments. You'll need to set up a global variable called playerMovePosition and set that in the update.. then Invoke MovePlayer

    A second option is to use a Coroutine. That is where you would call WaitForSeconds(). You can not just use yield return in your main program.
     
  27. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    The example I gave you was only for chaining objects, and I gave you an example of how you could do movement only. I'm leaving it up to you to build on that for your own implementation. If you want someone to code more of it for you, you could try asking over in the Collaboration subforum.

    WaitForSeconds takes seconds, not milliseconds.