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
  4. Dismiss Notice

Camera moving on the Z axis when the player is running (platformer game 2.5D)

Discussion in 'Scripting' started by DrSpoutnik, May 28, 2020.

  1. DrSpoutnik

    DrSpoutnik

    Joined:
    Jan 14, 2018
    Posts:
    64
    Hi everyone !

    I'm a newbie here and with Unity.
    i try to build my own platformer game, in 2.5D (let's say in the way of Inside, Antother world...).

    my player (in 3D in 3D world) can only move on the X axis (walk, run, crouch...).
    I would like the Camera moves on the Z axis when the player is running, like a zoom out. But i prefer not use camera depth and really move the camera.
    and i want the movement to be progressive and smooth.
    For instance : let's say the camera is at 0 on the Z axis by default, when the caracter starts to run, the camera goes from 0 to 150 on the Z Axis in 0,5 seconds, stay at 150 as long as he runs, and come back to 0 as he stops...

    I don't know how to proceed... did a lot of tests but i don't understand enough code to achieve that... maybe someone could help me a bit here ?

    i already have a controller script for my camera (cameraFollow)
    and a controller for my player.

    I tried to ad an "Animator component" on my camera, with three "motions", CameraIddle (at 0) CameraZoomIn (0 to 150 in 0,5 sec) and CameraZoomOut (150 to 0 in 0,5 sec) and to associate to the Running key first in the Player controller script, thant in camera controller script, but didn't work.
    i tried several things that i barely understood, found on forums but nothing worked...

    Thanks !
     
    Last edited: May 28, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    I did this in my Impulse One game: I mapped camera Z to speed in the same way (I think) you want.

    Here was what I did:

    My camera controller has:

    - 2 preset distances: near and far. These are set up for a given level.

    - 2 preset player velocities, min and max, also set up for level

    The above min/max velocities are mapped to the Z distance, as follows:

    Each frame the camera controller reads the player's velocity magnitude.

    - First it uses
    Mathf.InverseLerp(minSpeed, maxSpeed, currSpeed)
    to end up with 0 to 1 speed fraction

    - Now feed that speed fraction into
    Mathf.Lerp( nearZ, farZ, speedFraction)
    to get a desired Z

    If you feed that Z straight into the camera it is jerky, especially if you accelerate really hard or stop suddenly.

    Instead, do a time filtered tween, keeping another "current Z" and using some fraction to lerp towards it smoothly, something like this:

    Code (csharp):
    1. float currentZ; // member variable
    and in your camera update:

    Code (csharp):
    1. // how we get desiredZ, as described above
    2. float desiredZ = Mathf.Lerp( nearZ, farZ, speedFraction);
    3.  
    4. const float Snappiness = 2.0f;  // how quickly the camera pulls back/forward
    5.  
    6. // this filters it to be smoother
    7. currentZ = Mathf.Lerp( currentZ, desiredZ, Snappiness * Time.deltaTime);
    8.  
    9. // now use currentZ to position your camera's Z position
    10.  
    That should get you a long way towards what you're looking for. Fiddle with the numbers to change the characteristics of it.
     
  3. DrSpoutnik

    DrSpoutnik

    Joined:
    Jan 14, 2018
    Posts:
    64
    Thanks a lot Kurt !
    your solution seems really better.
    i'm a very beginner in code, so i'm sorry to ask but how do you assign these presets for the distance "near" and "far" ? and for min & max velocity as well ?

    thanks !
     
    Kurt-Dekker likes this.
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,779
    For the first cut you can just put them right in the code as constants:

    Code (csharp):
    1. const float minZ = 10;
    2. const float maxZ = 20;
    etc.

    Then get everything plumbed so that at least it works a bit, and then you can go back and either tweak it in code, OR... the Unity way is to make those values public so you can tweak them in the inspector.

    Code (csharp):
    1. public float minZ;
    2. public float maxZ;
    For extra bonus points, add a Reset() function like so:

    Code (csharp):
    1. void Reset()
    2. {
    3.   minZ = 10;
    4.   maxZ = 10;
    5. }
    And that is the reference way to set up presets in Unity-land.

    Having a Reset() function lets you right-click on the hamburger in the upper right corner of the inspector panel for this script and reset those values to know values. Plus Reset() is called when the Monobehavior is added.
     
  5. Giustitia

    Giustitia

    Joined:
    Oct 26, 2015
    Posts:
    113
    I would also recommend you to take a look to Unity's Cinemachine. It's easy to use and very powerful when you seek for a more cinematographic camera :D
     
    Kurt-Dekker and PraetorBlue like this.
  6. DrSpoutnik

    DrSpoutnik

    Joined:
    Jan 14, 2018
    Posts:
    64
    Thanks you both of you !
    i'll try your method kurt but it's a little bit hard for me since i don't understand code even if i try !

    i'lll have a look with cinemachine Giusttita, looks great !