0
\$\begingroup\$

I have a 3rd person camera controller in a top-down game. I have my cameran following the player and I currently use linear interpolation to make the movement smooth and a little laggy. But I would like to do the opposite: when the player moves in a certain direction the camera moves a little bit ahead, so as to reveal more of what is ahead of the player.

    void Update ()
    {
            var newX = player.transform.position.x;
            var newZ = player.transform.position.z - 17;
            var y = transform.position.y;
            var targetPosition = new Vector3 (newX, y, newZ);
            transform.position = Vector3.Lerp (transform.position, targetPosition, 0.01f);  
    }
\$\endgroup\$
  • \$\begingroup\$ ad a portion of the speed vector to newX,y,newZ \$\endgroup\$ – ratchet freak Nov 21 '13 at 15:52
  • \$\begingroup\$ If you are moving the camera at all, and understand what you are doing, modifying this movement with a simple behavior change should be relatively trivial. So rather than try to figure out how to do something specific, make sure you understand your linear algebra, and the relationship it has with camera systems in games. \$\endgroup\$ – Evan Nov 21 '13 at 16:02
  • \$\begingroup\$ @ratchetfreak the camera does not have speed, its just chasing the players position. I tried adding to the targetPosition but could not get any result. Can you give an example? \$\endgroup\$ – Daarwin Nov 21 '13 at 16:09
  • \$\begingroup\$ I meant the player's speed \$\endgroup\$ – ratchet freak Nov 21 '13 at 16:14
  • \$\begingroup\$ @ratchetfreak Dont you mean players moving direction? \$\endgroup\$ – Daarwin Nov 21 '13 at 16:16
4
\$\begingroup\$

This is a lot easier when you put an emplty child object on your character for the camera to track instead.

Imagine your player is being pulled by an invisible dog whenever he moves and when not moving the dog sits next to the player. If your camera is lerping its position to that invisible dog instead of the player, the result is your character still moves and is controller by your character controller but your camera tracks ahead to the empty game object (or our invisible dog called Bingo.)

If you want the camera to always be ahead of the character then child an empty game object to your player and place it N number of units ahead of your character (however far you like according to your prefences.) If you want it to return to the player when he isn't moving then leave it at 0,0,0 local position.

In your script (which I assume is attached to the camera) you can reference that objects transform using the Unity3D insepctor instead of using your player transform so your camera will lerp toward where the player is looking.

public Transform trackingHelper;

void Update ()
{
        var newX = trackingHelper.position.x;
        var newZ = trackingHelper.position.z - 17;
        var y = transform.position.y;
        var targetPosition = new Vector3 (newX, y, newZ);
        transform.position = Vector3.Lerp (transform.position, targetPosition, 0.01f * Time.deltaTime);  
}

Please note: as you are using Update and not FixedUpdate that you should multiply your last Lerp argument by Time.deltaTime to attribute for frame stutter.

If you want it so this only occurs when your character moves then you can lerp the position of the child empty game object in another script so that it moves from 0 to N units when the player is moving. I am assuming the axis is the Z axis for the tracking helper being 5 units in front of your player and that this script is attached to the helper itself:

public float distanceAhead = 5f;
public GameObject character;

private Vector3 prevPosition;

void Update()
{
     float newZ = 0; 
     if(!CheckCharacterIdle){
         newZ = distanceAhead;
     }
     Vector3 targetPosition = new Vector3(0,0,newZ);

     transform.localPosition = Vector3.Lerp (transform.position, targetPosition, 0.01f * Time.deltaTime);  
}

//If your characters utilise rigidbodies you can probably use
// the isSleeping() function to check for movement / interaction
// otherwise use manual comparison of position each frame
bool CheckCharacterIdle(){
    Vector3 curPos = character.transform.position;
    if(lastPos == curPos){
        lastPos = curPos;
        return true;
    }else{
        return false;
    }
}

This should sort the issue, I hope it helps.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ +1 for being pulled by an invisible dog. A great mental image when combined with many of the oh so serious games of today. \$\endgroup\$ – Christian Jan 6 '14 at 16:32
  • 1
    \$\begingroup\$ @Christian Well it helped me understand what I needed to do with my turret defense concept while dragging around the screen, my partner mentioned "So the camera is getting pulled around like it's walking the dog" and something clicked that you shouldn't make the camera try and stay ahead of the player but do it the other way around, have the player follow the camera. \$\endgroup\$ – Tom 'Blue' Piddock Jan 6 '14 at 17:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.