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

Question Parallax-Scrolling Effect Adding Offset in X-Axis

Discussion in 'Scripting' started by Payaso_Prince, Jun 10, 2023.

  1. Payaso_Prince

    Payaso_Prince

    Joined:
    Jul 17, 2017
    Posts:
    85
    What I am trying to accomplish:

    • I want to add a parallax effect to the background of my game.

    • I am working in 3D space with a perspective camera.
    Why:

    • The reason that I want to add a parallax movement script even though I'm already using a perspective camera, is so I can keep all of my background layers the same scale.
    • Rather than dragging different layers further back in the Z-axis, I want to keep all of the layers at the same position in the z-axis so they remain uniform in scale.
    The issue:

    • Currently, the code that I am using creates a working parallax effect.
    • However, the script is adding an offset in the x-axis to the game object it is attached to.
    • The offset amount is based on the variable 'parallaxEffectAmount'.
    • When parallaxEffectAmount is 0, the offset issue is gone and the layer is positioned at it's correct x-position in the scene. However, the parallax effect is gone.
    The code I am currently using:

    Code (CSharp):
    1. public class ParallaxScroll : MonoBehaviour
    2. {
    3.  
    4. private float startPos;
    5. [SerializeField] Camera cam;
    6. [SerializeField] private float parallaxEffectAmount;
    7.  
    8. // Start is called before the first frame update
    9. void Start()
    10. {
    11.     startPos = transform.position.x;
    12. }
    13.  
    14. // Update is called once per frame
    15. void Update()
    16. {
    17.     float distance = (cam.transform.position.x * parallaxEffectAmount);
    18.     transform.position = new Vector3(startPos + distance, transform.position.y, transform.position.z);
    19. }
    20. }

    • Is there anyway I can implement a parallax effect for my background layers that will keep their original x-positions in the scene?

      Does anyone have a better method of accomplishing this?

      Thanks so much for taking the time! :)
     
    Last edited: Jun 10, 2023
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Usually you dupe the repeating stuff in the back enough times to cover the entire screen plus one extra chunk.

    Finally when scrolling laterally for the faked parallax, after computing the X-offset, you simply modulo the X-offset by the size of the repeating artwork.

    If you were a distant god gazing down on this, that one chunk would jerk laterally every time it wrapped modulo.

    When you're looking at it through the clamped viewport of the camera, it looks perfect.

    Smoke and mirrors FTW!

    EDIT: this isn't only for parallax. You can use it for ANY endless thing you want, mountains, etc.
     
  3. Payaso_Prince

    Payaso_Prince

    Joined:
    Jul 17, 2017
    Posts:
    85
    The legendary Kurt :cool:
    Thanks for the reply man!

    Though, I don't want to have a repeating background. I'd like to place things manually and have them not be endless.
    Any idea how I can accomplish this? :confused:
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Yeah you do! :)

    "What?! No I don't!" you say

    Wait for it... wait for it... Yes you do.. Here's how:

    At level start:

    - you Instantiate() a fresh copy of the entire span of your background
    - you offset it laterally as far as it needs to be to perfectly wrap around.

    Now... run this script... I just ripped out of an old scrolling mountain background and blew the dust off it:

    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. // @kurtdekker - cheeseball endless lateral wrapping
    6. //
    7. // To set up:
    8. //    - make a blank GameObject with this script
    9. //    - parent precisely-spaced dupes of your backdrop to this GameObject
    10. //    - set the arguments to this script
    11. //
    12. // To use:
    13. //    - move this transform in your Update()
    14. //    - this will use modulo to wrap laterally
    15. //
    16. // To test trivially:
    17. //    - put a bunch of evenly-spaced spheres as children to this
    18. //    - scroll this object left / right in space
    19. //    - watch how it modulo-snaps
    20.  
    21. public class EndlessXWrapper : MonoBehaviour
    22. {
    23.     [Header("This is the left edge of your span.")]
    24.     public float HomeXPosition = 0.0f;
    25.     [Header( "And this is your span.")]
    26.     public float WrappingInterval = 1.0f;
    27.  
    28.     void LateUpdate ()
    29.     {
    30.         Vector3 position = transform.position;
    31.  
    32.         float x = position.x;
    33.  
    34.         x -= HomeXPosition;
    35.  
    36.         if (x < 0) x += WrappingInterval;
    37.         if (x >= WrappingInterval) x -= WrappingInterval;
    38.  
    39.         x += HomeXPosition;
    40.  
    41.         position.x = x;
    42.  
    43.         transform.position = position;
    44.     }
    45. }
     
  5. Payaso_Prince

    Payaso_Prince

    Joined:
    Jul 17, 2017
    Posts:
    85
    I don't want them to repeat though ._.
    You really should not insist on something else.

    At any rate, I went with a different approach that seems to work perfectly.
    This is the code. I hope it helps someone else in the future:


    Code (CSharp):
    1. public class ParallaxScroll1 : MonoBehaviour
    2. {
    3.  
    4.     public float percentX;
    5.     public float percentY;
    6.     [SerializeField] private Camera cam;
    7.     Vector3 camPrev;
    8.  
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.         camPrev = cam.transform.position;
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void LateUpdate()
    18.     {
    19.         Vector3 camPos = cam.transform.position;
    20.         float deltaX = camPos.x - camPrev.x;
    21.         float deltaY = camPos.y - camPrev.y;
    22.  
    23.         float adjustX = deltaX * percentX;
    24.         float adjustY = deltaY * percentY;
    25.  
    26.         transform.position = transform.position + new Vector3(adjustX, adjustY, 0);
    27.  
    28.         camPrev = camPos;
    29.     }
    30. }
     
    Last edited: Jun 10, 2023