3
votes

When reading this, keep in mind I'm new to both programming and Unity, so I might be missing some terms or tools Unity offer. Please elaborate your answers in an ELI5 manner. Thanks in advance!

I am currently working on some game-physics for a small personal project. Currently I've created a platform, a character and what should be, a following companion.

However, since I'm still not on a level, where I can create perfect code on own hand, I found an "enemy" script and tried to modify it a bit. It Works to an extend, but it needs some tweaks which I hope I can help aquire with you guys.

This is how it looks now (the orange square is the companion)

enter image description here

It follows the player, and I can tweak the speed to fit as a companion, and not a player. However, as the Picture presents, the companion runs for the center of the player. What I want to create is a companion which follows the player, but still keeps a small gap from the player.

My first thoughts was to create some kind of permanent offset, but I fail to figure out how to do this without messing up the follow function.

I hope you can help me, it will be much appreciated!

Here's the code for reference.

Code attached to Player:

using UnityEngine;
using System.Collections;

public class PlayerCompanion : MonoBehaviour
{

    //In the editor, add your wayPoint gameobject to the script.
    public GameObject wayPoint;

    //This is how often your waypoint's position will update to the player's position
    private float timer = 0.5f;

    void Update ()
    {
        if (timer > 0) {
            timer -= Time.deltaTime;
        }
        if (timer <= 0) {
            //The position of the waypoint will update to the player's position
            UpdatePosition ();
            timer = 0.5f;
        }
    }

    void UpdatePosition ()
    {
        //The wayPoint's position will now be the player's current position.
        wayPoint.transform.position = transform.position;
    }
}

Code attached to companion:

using UnityEngine;
using System.Collections;

public class FollowerOffset : MonoBehaviour {

    //You may consider adding a rigid body to the zombie for accurate physics simulation
    private GameObject wayPoint;

    private Vector3 wayPointPos;

    //This will be the zombie's speed. Adjust as necessary.
    private float speed = 10.0f;

    void Start ()
    {
        //At the start of the game, the zombies will find the gameobject called wayPoint.
        wayPoint = GameObject.Find("wayPoint");
    }

    void Update ()
    {
        wayPointPos = new Vector3(wayPoint.transform.position.x, transform.position.y, wayPoint.transform.position.z);
        //Here, the zombie's will follow the waypoint.
        transform.position = Vector3.MoveTowards(transform.position, wayPointPos, speed * Time.deltaTime);
    }

}

bump, I guess ? :)

2
If you add a rigid body to both, then Unity's built-in physics will prevent the follower moving "into" the target. - Micky
@MickyDuncan tried adding rigid body to both objects, doesn't seem to change anything - user3275104
Oh you're using Vector3.MoveTowards() - that overrides rigid bodies. Check this out answers.unity3d.com/questions/368727/… - Micky
So I'm trying to use the code your link presents, however I get an error at: "var dir: Vector3" ":" is an unexpected symbol. Am I placing that code the wrong place? Currently I got it all placed at void Update() - user3275104
Their example is UnityScript. The c# code would be var dir = targetPos - transform.position; For help converting see m2h.nl/files/js_to_c.php - Micky

2 Answers

1
votes

You can use smooth follow script. I have created a sample class for you. This class has features to follow any given gameobject with some delay and offset. You will have to tweak some values according to your need.

using UnityEngine;
using System.Collections;

public class PlayerCompanion : MonoBehaviour
{
    [SerializeField]
    private GameObject wayPoint;
    [SerializeField]
    public Vector3 offset;
    public Vector3 targetPos;//Edit: I forgot to declare this on firt time
    public float interpVelocity;
    public float cameraLerpTime = .1f;
    public float followStrength = 15f;

    // Use this for initialization
    void Start ()
    {
        //At the start of the game, the zombies will find the gameobject called wayPoint.
        wayPoint = GameObject.Find("wayPoint");
        offset = new Vector3 (5,0,0);//input amount of offset you need
    }

    void FixedUpdate () {
        if (wayPoint) {
            Vector3 posNoZ = transform.position;

            Vector3 targetDirection = (wayPoint.transform.position - posNoZ);
            interpVelocity = targetDirection.magnitude * followStrength;
            targetPos = transform.position + (targetDirection.normalized * interpVelocity * Time.deltaTime); 

            transform.position = Vector3.Lerp (transform.position, targetPos + offset, cameraLerpTime);
        }

    }
}

Attach this class to your player companion, play with different values.

0
votes

To preserve object orientation your companion schould not be anyways child of your main character.

Your wayPoint doesn't needs to be a GameObject but a Transform instead and your code will looks like better.

If your game is a 2D platform your and your companion needs to be backwards your player it probabli applys to just one axis (X?) so you can decrement your waiPoint in a more directly way by calculating it on your UpdatePosition function like this:

wayPoint.position = transform.position * (Vector3.left * distance);

where your "distance" could be a public float to easily setup.

so on your companion script Update just do:

transform.position = Vector3.MoveTowards(transform.position, wayPoint.position, speed * Time.deltaTime);

I can't test it right now so you could have problems with Vector3 multiply operations, just comment and I'll try to fix as possible ;)