How to make finite parallax

Hello, how do i make my parallax bakcground to be on center of camera, if player on center of the map. And if player in corner parallax camera will be in corner.
Right now i have this setup, but corners are not perfect.
My parallax background is child of main camera.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowUV_2 : MonoBehaviour
{
    public GameObject player;
    public float parralax = 10f;
    void Update()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        MeshRenderer mr = GetComponent<MeshRenderer>();
        Material mat = mr.material;
        Vector2 offset = mat.mainTextureOffset;

        offset.x = -transform.position.x / -transform.localScale.x / parralax;
        offset.y = -transform.position.y / -transform.localScale.y / parralax;

        mat.mainTextureOffset = offset;
    }
}

Bump. Still cant find a solution

I found the solution that almost works perfect, but i cant unbound if from camera. When it reaches corners
Animation5

Also i have this problem, if player reaches -X-Y or higher than 180,125 parallax moves to fast

Animation4

using UnityEngine;

public class ParallaxBG : MonoBehaviour
{
    public Camera mainCamera;                   // Reference to the main camera
    public GameObject player;                    // Reference to the player
    public float parallaxFactor = 0.5f;         // Parallax factor (0 < parallaxFactor < 1)
    public Vector2 mapBoundsMin;                // Minimum bounds of the map
    public Vector2 mapBoundsMax;                // Maximum bounds of the map
    public Vector2 backgroundSize;              // Size of the background

    private Vector2 previousPlayerPosition;     // Track the previous player position

    private void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        // Initialize the previous player position to the player’s starting position
        previousPlayerPosition = player.transform.position;

        // Set the initial position of the background
        UpdateBackgroundPosition();
    }

    private void Update()
    {
        UpdateBackgroundPosition();
    }

    private void UpdateBackgroundPosition()
    {
        player = GameObject.FindGameObjectWithTag("Player");
        mainCamera = Camera.main;
        // Get the current player position
        Vector2 playerPosition = player.transform.position;

        // Calculate the player's movement since the last frame
        Vector2 playerMovement = playerPosition - previousPlayerPosition;

        // Calculate new background position based on player's movement and parallax factor
        Vector3 newBackgroundPosition = transform.position - (Vector3)(playerMovement * parallaxFactor);

        // Update the previous player position to the current position
        previousPlayerPosition = playerPosition;

        // Calculate camera view boundaries
        float cameraHeight = mainCamera.orthographicSize * 2;
        float cameraWidth = cameraHeight * mainCamera.aspect;

        Vector2 cameraMin = new Vector2(mainCamera.transform.position.x - cameraWidth / 2, mainCamera.transform.position.y - cameraHeight / 2);
        Vector2 cameraMax = new Vector2(mainCamera.transform.position.x + cameraWidth / 2, mainCamera.transform.position.y + cameraHeight / 2);

        // Ensure the background stays in the camera view
        newBackgroundPosition.x = Mathf.Clamp(newBackgroundPosition.x, cameraMin.x, cameraMax.x);
        newBackgroundPosition.y = Mathf.Clamp(newBackgroundPosition.y, cameraMin.y, cameraMax.y);

        // Keep the background within the map bounds as well
        newBackgroundPosition.x = Mathf.Clamp(newBackgroundPosition.x, mapBoundsMin.x + (backgroundSize.x / 2), mapBoundsMax.x - (backgroundSize.x / 2));
        newBackgroundPosition.y = Mathf.Clamp(newBackgroundPosition.y, mapBoundsMin.y + (backgroundSize.y / 2), mapBoundsMax.y - (backgroundSize.y / 2));

        // Update the background position
        transform.position = newBackgroundPosition;
    }
}

I’m mostly ignorant on the specific issues 2D developers face but what is wrong with just creating a big textured static quad for the background? Parallax simulates something you get for free in a 3D engine, no?

Because my background image is low resolution, cant make that big image for static bg

Here you go:

ParallaxBG_1

DrawFullscreenOrthographicQuad.cs

using System;
using UnityEngine;

[ExecuteInEditMode]
public class DrawFullscreenOrthographicQuad : MonoBehaviour
{
    [SerializeField] Camera _camera;
    [SerializeField] Rect _worldRect = new Rect( Vector2.zero , new Vector2(80,40) );
    [SerializeField] Vector2 _quadSize = new Vector2(32,16);
    [SerializeField] Material _quadMaterial;
    [SerializeField][Range(0,1)] float _quadDepth = 0.99f;

    Mesh _quadMesh;
    Vector2 _quadSizeCorrected, _quadPos, _camSize;
    Vector3 _camPos;

    void Awake ()
    {
        _quadMesh = Resources.GetBuiltinResource<Mesh>("Quad.fbx");
    }

    void Update ()
    {
        if( _camera!=null )
        {
            float camOrthoSize = _camera.orthographicSize;
            float camAspect = _camera.aspect;
            _camSize = new Vector2( camOrthoSize*2f*camAspect , camOrthoSize*2f );
            Vector2 camSizeHalf = _camSize * 0.5f;
            _camPos = _camera.transform.position;

            // correct for scenario when camera aspect is larger than provided quad size
            _quadSizeCorrected = new Vector2(
                Math.Max( _quadSize.x , camOrthoSize*2f*camAspect ) ,
                Math.Max( _quadSize.y , camOrthoSize*2f )
            );
            Vector2 quadSizeHalf = _quadSizeCorrected * 0.5f;

            // find quad position:
            Vector2 srcmin = _worldRect.min + camSizeHalf;
            Vector2 srcmax = _worldRect.max - camSizeHalf;
            Vector2 dstmin = _worldRect.min + quadSizeHalf;
            Vector2 dstmax = _worldRect.max - quadSizeHalf;
            Vector2 t = new Vector2(
                Mathf.InverseLerp( srcmin.x , srcmax.x , _camPos.x ) ,
                Mathf.InverseLerp( srcmin.y , srcmax.y , _camPos.y )
            );
            _quadPos = new Vector2(
                Mathf.Lerp( dstmin.x , dstmax.x , t.x ) ,
                Mathf.Lerp( dstmin.y , dstmax.y , t.y )
            );
            float quadPosZ = _camPos.z + _camera.farClipPlane * _quadDepth;

            // correct for out of world bounds situations:
            _quadPos = Vector2.Max( _quadPos , (Vector2)_camPos-quadSizeHalf+camSizeHalf );
            _quadPos = Vector2.Min( _quadPos , (Vector2)_camPos+quadSizeHalf-camSizeHalf );
            
            // draw a quad:
            Graphics.DrawMesh(
                _quadMesh ,
                new Matrix4x4(
                    new Vector4( _quadSizeCorrected.x , 0 , 0 , 0 ) ,
                    new Vector4( 0 , _quadSizeCorrected.y , 0 , 0 ) ,
                    new Vector4( 0 , 0 , 1 , 0 ) ,
                    new Vector4( _quadPos.x , _quadPos.y , quadPosZ , 1 )
                ) ,
                _quadMaterial ,
                1
            );
        }
    }

#if UNITY_EDITOR
    void OnDrawGizmos ()
    {
        // world bounds:
        Gizmos.color = Color.red;
        Gizmos.DrawWireCube( _worldRect.center , _worldRect.size );

        if( _camera!=null )
        {
            // camera rect:
            Gizmos.color = Color.cyan;
            Gizmos.DrawWireCube( (Vector2)_camPos , _camSize );

            // quad rect:
            Gizmos.color = Color.yellow;
            Gizmos.DrawWireCube( _quadPos , _quadSizeCorrected );
        }
    }
#endif

}

The way it works it renders a quad with given material at some depth

The main problem here was how to calculate this quad’s center. Tried few ugly solutions that didn’t work at all. After drawing these gizmos I realized that the nicest solution should be to linearly interpolate between some min and max points - this is what I ended up doing.

How do i make it background move away when player reach corners. Right now its bound to camera
Animation5

If you want the quad to be bounded by _worldRect then comment out these two lines: