0
\$\begingroup\$

My player is jumping on sticks, endlessly going upwards, and if they fall, it's game over.

I want the camera to follow the player only when they move up (ie. only on Y axis), not down. If they move down (fall), the character dies, and the camera does not follow down them (only up).

How do I implement this behaviour in a Unity C# script?

\$\endgroup\$
2
  • \$\begingroup\$ How have you set up your camera follow behaviour so far? (Show us the relevant code or game entity configuration in-editor) \$\endgroup\$
    – DMGregory
    Apr 16 at 17:54
  • \$\begingroup\$ I have not set up camera follow yet. I'm open to anything at the moment. \$\endgroup\$
    – jukvox
    Apr 16 at 19:29

3 Answers 3

0
\$\begingroup\$

I'd do this in LateUpdate to ensure the camera moves after the player, as liggiorgio suggests. This avoids judder where we smoothly follow the player but then the player moves relative to the screen, breaking the smoothness.

I'd also use SmoothDamp to smooth the camera's motion, so it doesn't jerk from a stop into motion and then back to a stop. This adds a little momentum blending which you can control with the smoothDampTime variable (smaller values = faster following, larger values = smoother, but the player might outrun it in short bursts of speed).

Adding an offset so the camera aims above the player can help them see more of what's ahead, and give some buffer space so the smoothing doesn't make us fall behind the player.

Put a script like this on your camera object and assign the player character as its followTarget.

using UnityEngine;

public class SmoothUpwardFollow : MonoBehaviour
{
    public Transform followTarget;

    [Tooltip("How far above the player the camera should aim, in world units")]
    public float offset = 0f;

    [Tooltip("How gently the camera should accelerate/decelerate — small values are more responsive")]
    public float smoothDampTime = 0.2f;
    
    // Used to ensure camera's speed is continuous, not jerky.
    float _velocity;

    // Update at end of frame, after player character
    // has finished moving in Update or FixedUpdate.
    void LateUpdate() {
        var pos = transform.position;

        // Max ensures we only move up, not down.
        float targetHeight = Mathf.Max(pos.y,  followTarget.position.y + offset);

        // Smoothly chase targetHeight on y axis.
        pos.y = Mathf.SmoothDamp(
            pos.y,
            targetHeight,
            ref _velocity,
            smoothDampTime
        );
        
        // Apply smoothed chasing position to
        // this (camera) object's transform.
        transform.position = pos;
    }
}
\$\endgroup\$
0
\$\begingroup\$

2d?

You could do:

using UnityEngine;

public class FollowPlayerScript : MonoBehaviour
{
    public GameObject cam; // the camera game object
    public GameObject player; // the player
    private float camY; //the highest y the player has reached
    public float yThreshold; //how far the player has to be below the cam to die

    // Update is called once per frame
    void Update()
    {
        if (player.transform.position.y > camY)
        {
            camY = player.transform.y
            cam.transform.y = camY
        }
        else
        {
            if (cam.transform.position.y - player.transform.position.y > yThreshold)
                //kill the player
        }
        
    }
}

This method doesn't handle easing though. And it might contain some spelling or syntax problems because I was doing this on mobile. But I think this should wirk for now!

\$\endgroup\$
2
  • \$\begingroup\$ transform does not have a property y. You probably meant to cache the value of transform.position to a local variable, overwrite its .y, then reassign the changed version back to transform.position. \$\endgroup\$
    – DMGregory
    Apr 17 at 10:10
  • \$\begingroup\$ Yeah I meant transform.position.y. And also what I just realized is that you cant just call cam.transform.y = camY, you need to do cam.transform.position = new Vector3(cam.transform.position.x, camY, cam.transform.position.z) \$\endgroup\$
    – CheckerT
    Apr 17 at 14:23
0
\$\begingroup\$

If the camera and the player were independent GameObjects, a viable strategy would be:

  1. Update the player's position first.
  2. Update the camera's position last.

The camera always updates its position after the player has moved, without necessarily moving from its previous position: you must update its transform.y value only if it is below the current player's transform.y value; otherwise, do nothing because the player has moved below the last camera maximum altitude.

I'm not providing any code snippet because your question is open-ended, and my proposed solution can be implemented in many different ways (e.g. game loop and Hierarchy, script override order, state machines...). Edit your question to reduce the scope of your problem or show your current implementation, and I'll update my answer accordingly.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .