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

2D walking script with perspective

Discussion in '2D' started by Daan_123, Jan 26, 2019.

  1. Daan_123

    Daan_123

    Joined:
    Nov 5, 2018
    Posts:
    3
    Hello People,

    I am very new to making games and especially with c#. However, the game that I am currently working has one particular aspect that seems very difficult to code. Most things in c#, like player movement, are pretty easy to google but the thing that I'm looking for is hard to search for. Therefor I'm hoping that maybe one of you fine geniuses could help me out with this problem:

    The game is want to make is a 2D point and click game that is set in a single room and the player controles a character that can move around freely. The 'camera' show a single corner of the room and is always static and whenever the player walks out of frame they will see a different corner of the room (hope that makes sense). The player can go left, right, 'up' and 'down'. Pretty easy to code right? Here's the issue; The view of the game is on the same hight as the eyes of the character. So when the player is walking trough the room the walking speed should speed up or slow down depending on how close the character is to the 'camera'.

    Hopefully all of that made sense. I would really appreciate if someone would right down some code that would solve this problem. I have no idea if this is easy or really hard to do, but I am already very grateful for all the help that i can get.


    Daan
     
  2. hlw

    hlw

    Joined:
    Aug 12, 2017
    Posts:
    250
    I'd love to help, but i don't understand what you actually mean.
    Can you make screenshots or drawings that will help me understand what you actually have and what you want it to be instead ?
     
  3. Daan_123

    Daan_123

    Joined:
    Nov 5, 2018
    Posts:
    3
    Thank you for your response, I understand that it is difficult to understand without images.

    Here is a simple illustration demonstrating what I mean. Character A would walk to left and right with much more speed because it is closer to the camera that character B.

    IMG_2720.JPG


    These are sketches for some of the backgrounds that the character can walk through:
    IMG_2717.JPG
    IMG_2718.JPG IMG_2719.JPG

    So the character that the player controles can walk anywhere in the rooms. The character and the backgrounds are all either 2D images or 2D animations. What I need is a script for the character movement that makes it that the character size shrinks or enlarges and walks slower or faster depending on how close he/she is to the 'camera'.

    Hopefully I explained myself a bit clearer this time. I would happily explain things again if something is still unclear. Thank you very much for your time.
     

    Attached Files:

  4. hlw

    hlw

    Joined:
    Aug 12, 2017
    Posts:
    250
    That makes way much more sense to me now. You want to somehow simulate the feel of perspective in full 2D rendering. This seems complicated if you try to do it with an orthographic camera (lot of maths, a really big lot of maths).

    You can set your camera to perspective mode, and modify the transform position z of your character, if your camera is rotated to look slightly toward the ground, everything will look like what you wanted to create.(I believe)

    This will work like any 3D game, the only difference being you work using 2D sprites.
     
  5. Daan_123

    Daan_123

    Joined:
    Nov 5, 2018
    Posts:
    3
    That is actually a really good idea, I hadn’t even thought about that. I’ll definitely try that out.

    Thank you so much, i’ll let you know if it worked out!
     
  6. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    So you need LucasArts adventure game like movement.

    You don't have to go overboard with math even if you want to stay full 2D. If you are using flat scenes (no meaningful height differences), then the movement isn't that hard to create so that it doesn't look strange.

    But if you haven't done any coding before, don't expect it to be easy, or that someone writes you all the code.

    The movement part isn't complicated at all.

    When you are moving up/forward in top down game (for example), along which axis are you moving? A: You are moving along vertical axis, as you don't have perspective in orthographic view... but when you are moving in perspective image, you have the concept of vanishing point. I think you know this, as you already have used it in your 1 point perspective images.

    So each frame you move, you are not moving along world axis, but the "y-axis movement" of character will be along a line defined by current position of character and an infinitely distant vanishing point.

    You can create this line like this - note that both points are just on flat XY plane (as this is 2D):

    Code (CSharp):
    1. var vertDir = (vanishingPoint.position - transform.position).normalized;
    Then you need some input. This is just Unity input, nothing special:

    Code (CSharp):
    1. // Get input
    2. var inputX = Input.GetAxisRaw("Horizontal");
    3. var inputY = Input.GetAxisRaw("Vertical");
    Now that you have this, you can move your character in Y-axis... You can't just add one y value, as you are now moving along both x and y like explained above:

    Code (CSharp):
    1. Transform.position += vertDir;
    Then the speed.

    When you are moving fastest and when slowest? So when you are near camera, at closest distance, you should be moving max speed, and when in some distance closest to vanishing point (whatever that is), you move using slowest speed.

    Just think in flat XY plane. Let's say vanishing point is at Y 10m and closest point is at Y 0. Then the max distance is just some distance closer to vanishing point. Depending on your setup, it could be 5m away from vanishing point in Y.

    To benefit from this, here's how you could do this, create a multiplier, that goes from 0-1 depending on distance:

    Code (CSharp):
    1. var multiplier = Mathf.Abs(vanishingPoint.position.y - hero.transform.position.y) / maxDistance;
    Now you have a number that gets smaller near vanishing point, and bigger when moving down (0-1). Then you can modulate you horizontal and vertical speed by this multiplier:

    Code (CSharp):
    1. // speed vert
    2. speedVert = Mathf.Lerp(0.2f, 3f, multiplier); // 0.2f and 3f are min and max move speeds
    3.  
    4. // Speed hor
    5. speedHor = Mathf.Lerp(0.2f, 3f, multiplier);
    So your final movement Y code would be like this:

    Code (CSharp):
    1. // Movement y, move towards vanishing point
    2. var vertDir = (vanishingPoint.position - hero.transform.position).normalized;
    3. var moveY = inputY * speedVert * Time.deltaTime;
    4. transform.position += vertDir * moveY;
    Then the x-movement is pretty much the same but you wouldn't have to use the movement towards vanishing point you can just move along x, like you've probably learned earlier already. Just multiply moveX too with speedHor multiplier.

    And colliding on side walls. I would just use 2d colliders to limit sideways max movement. Even working out rectangular limits on left and right is pure triangle math otherwise.

    I'll leave the sprite scaling and other stuff for you to figure out, this will get you started. I haven't ever done any setup like this yet, but this is pretty much how you can get this working IMHO.
     
    Last edited: Jan 28, 2019
  7. dabmantrips_unity

    dabmantrips_unity

    Joined:
    Sep 1, 2021
    Posts:
    4
    I'm going to revive this thread because I'm in dire need of understanding this concept and applying it to my game. I copied the code above and applied it to a 3D Rigidbody so I can utilize z axis movement and using a perspective camera to handle perspective projection scaling. Everything works fine but I need help understanding how to setup the vanishing point better. I'm using a cube for the vanish point location reference currently the character moves along a vanishing point line but how do I customize the angle of the line.

    Edit: Okay I see my problem I'm dealing with a 2 point perspective 2D drawing. How could I code a 2 point perspective movement script. I'll attach an example. 60d03f894bdab5c29d79e516f89aa345.jpg
     

    Attached Files:

    Last edited: Sep 2, 2021
  8. sam_nau

    sam_nau

    Joined:
    Oct 26, 2013
    Posts:
    9
    For those who want something that does 2D sprite scaling with simulated perspective it's actually not that complicated, provided that you supply a few "guardrails".
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PerspectiveScaleController : MonoBehaviour
    6. {
    7.     GameObject player;
    8.     float currentY;
    9.     [Range(0.0f, 1.0f)]
    10.     public float minScale = 0.4f;
    11.     [Range(0.0f, 1.0f)]
    12.     public float maxScale = 0.8f;
    13.     float scaleFactor;
    14.     [Range(0.0f, 20.0f)]
    15.     public float scaleAreaHeight = 13f;
    16.     void Start()
    17.     {
    18.         player = gameObject;
    19.         scaleFactor = maxScale - minScale;
    20.     }
    21.     float CalculateScale()
    22.     {
    23.         currentY = player.transform.position.y + ((scaleAreaHeight / 2));
    24.         float positionScale = currentY / scaleAreaHeight;
    25.         float targetPositionScale = positionScale >= 0 ? positionScale : 0;
    26.         float newPlayerScaleFactor = maxScale - (scaleFactor * targetPositionScale);
    27.         return newPlayerScaleFactor;
    28.     }
    29.     void SetPlayerScale()
    30.     {
    31.         float newPlayerScaleFactor = CalculateScale();
    32.         Vector3 newPlayerScale = new Vector3(newPlayerScaleFactor, newPlayerScaleFactor, 1);
    33.         player.transform.localScale = newPlayerScale;
    34.     }
    35.  
    36.     void Update()
    37.     {
    38.         SetPlayerScale();
    39.     }
    40. }
    Using this code you define what the minimum and maximum scale should be in a given scene. And then you also define what the "height" of the area is that the player is walking around in. The height is really the maximum distance from 0 of the player (above and below) you want the player to be moving around in to measure where the player is in that range. So if you want the player to scale when walking from Vector3(whateverX, -6f, 1f) to Vector3(whateverX, 6f, 1f) , would be
    scaleAreaHeight
    would be "12". Basically whatever viewable area you want to display this scale effect you need to set a value so that when the player walks around in that space, a percentage can be calculated of where the player is within that "height" limit.

    Once you know where the player is, percentage-wise, within that defined height, you take the difference between the min scale and max scale and multiply it by the percent value of where the player is
    scaleFactor * targetPositionScale
    and subtract that from the max scale to determine what the current player scale should be.

    Then you just use that value to set the scale of the player. Using these guardrails you can adjust the values to match your scene and scale the player with user movement, in however best matches the specific scene.