1
\$\begingroup\$

So, to keep it short, I am developing a simple top-down RPG. The player (and party) can only move in 4 directions. Seems really simple, but I have not been able to find a good answer on how to establish party movement and I think I have made it too complicated.

Here is the current code for the Player:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public float moveSpeed = 5f; public Rigidbody2D rb; public Animator animator; public Vector2 movement; // Update is called once per frame void Update() { // Input movement.x = Input.GetAxisRaw("Horizontal"); movement.y = Input.GetAxisRaw("Vertical"); animator.SetFloat("Horizontal", movement.x); animator.SetFloat("Vertical", movement.y); animator.SetFloat("Speed", movement.sqrMagnitude); if(Input.GetAxisRaw("Horizontal") == 1 || Input.GetAxisRaw("Horizontal") == -1 || Input.GetAxisRaw("Vertical") == -1 || Input.GetAxisRaw("Vertical") == 1) { animator.SetFloat("LastMovementX", Input.GetAxisRaw("Horizontal")); animator.SetFloat("LastMovementY", Input.GetAxisRaw("Vertical")); } if (Mathf.Abs(movement.x) > Mathf.Abs(movement.y)) { movement.y = 0; } else { movement.x = 0; } } void FixedUpdate() { //Movement rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime); } } 

This was from an online tutorial and I thought it was great! It works fine. the only issue I have is when I am making the player walk in one direction and press a different arrow-key, they point in that direction? I thought the (Mathf.Abs(movement.x) > Mathf.Abs(movement.y)) would also prevent that but I guess I was wrong. I have not found a straight answer on this either. I have tried this method:

if (Mathf.Abs(movement.x) > 0.01f) { movement.y = 0; // Disable vertical input if a horizontal key is pressed } if (Mathf.Abs(movement.y) > 0.01f) { movement.x = 0; } 

But this did not help. It didn't seem to change anything. It is supposed to negate the player character from detecting another arrow-key movement.

Now, onto the party issue. Initially, I thought I could just copy-paste everything from the player character and just make sure to switch things around, but that seemed to be harder than I thought. This is the code for my party sprite:

using System.Collections; using System.Collections.Generic; using UnityEngine; public class FollowPlayer : MonoBehaviour { public GameObject leader; // the game object to follow - assign in inspector public int steps; // number of steps to stay behind - assign in inspector public int distance; //consistant distance to stay away from player - assign in inspector public float moveSpeed = 5f; public Rigidbody2D rb; public Animator animator; private Queue<Vector3> record = new Queue<Vector3>(); private Vector3 lastRecord; private Vector2 movement; void Update() { movement.x = Input.GetAxisRaw("Horizontal"); movement.y = Input.GetAxisRaw("Vertical"); //set animations animator.SetFloat("Horizontal", movement.x); animator.SetFloat("Vertical", movement.y); animator.SetFloat("Speed", movement.sqrMagnitude); if(Input.GetAxisRaw("Horizontal") == 1 || Input.GetAxisRaw("Horizontal") == -1 || Input.GetAxisRaw("Vertical") == -1 || Input.GetAxisRaw("Vertical") == 1) { animator.SetFloat("LastMovementX", movement.x); animator.SetFloat("LastMovementY", movement.y); } if (Mathf.Abs(movement.x) > Mathf.Abs(movement.y)) { movement.y = 0; } else { movement.x = 0; } } void FixedUpdate() { // record position of leader record.Enqueue(leader.transform.position); //Movement rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime); // remove last position from the record and use it for our own if (record.Count > steps) { this.transform.position = record.Dequeue(); } } } 

I essentially did copy all of the movement logic from my player. For the most part, it works pretty well. However, there is no delay, so the movement from the party sprite looks awkward (it is turning too quickly for example, which makes sense since it is just following the code I have for it). I want it to seem more like a snake.

Another thing that I had a lot of trouble with was the spacing between the player sprite and the party sprite. I was trying to make a new initial position for the party sprite but none of it seemed to help. I thought I could just mess with the collisions, but I wanted to make sure I wasn't missing anything when using this method.

I got the code at the bottom from this response: 2D party follow the leader in Unity?

This answer helped me tremendously, but I am still so confused on what the commenter meant in regards to not applying the dequeue if I want to make space between the player and party sprite.

I appreciate the help! Thank you!

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

Don't listen to input for the followers. Since you seem to know where you want them relative to the player, use relative vectorization.

public class Follower : MonoBehaviour { [SerializeField] private Transform playerTransform; [SerializeField] private Vector2 followerOffset; // Offset from player where the follower should move // you can adjust this in the inspector at runtime [SerializeField] private Rigidbody rb; [SerializeField] private float followForce = 5f; // Tuning value for how strong the follower moves private void FixedUpdate() { // Determine the target position by applying the follower offset Vector3 targetPosition = playerTransform.position + (Vector3)followerOffset; // Calculate direction to the target Vector3 direction = (targetPosition - transform.position); rb.AddForce(direction.normalized * followForce, ForceMode.Force); // Use ForceMode.Force to make it consistent across FixedUpdate calls // Never multiply force by deltaTime } } 

This will get you pretty close and I will leave animation and smoothing for you to do.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.