unity2d 自动化视差滚动背景

前言

虽然挺简单的,不过逛了一圈没看到,干脆分享下

核心逻辑就是给克隆每个子对象并生成对应的父对象,之后控制这些新父对象进行滚动

使用

将背景按顺序拖拽到同一父对象上,设定背景图层顺序,将脚本挂载到父级即可

public class ParallaxBackground : MonoBehaviour
{
    
    
    private GameObject cam;

    /// <summary>
    /// 视差效果
    /// </summary>
    [SerializeField] private float[] parallaxEffect;

    private float xPosition;
    private float bkLength;
    private Transform[] layers;
    private Transform[] originLayers;

    private void Start()
    {
    
    
        cam = Camera.main.gameObject;

        bkLength = GetComponentInChildren<SpriteRenderer>().bounds.size.x;

        xPosition = transform.position.x;

        layers = new Transform[transform.childCount];
        // unity改动子元素会实时影响childCount,所以先保存
        originLayers = new Transform[transform.childCount];
        for (int i = 0; i < transform.childCount; i++)
        {
    
    
            originLayers[i] = transform.GetChild(i);
        }
        for (int i = 0; i < originLayers.Length; i++)
        {
    
    
            // 创建新父对象作为背景和克隆背景的父级,方便整体移动
            Transform layer = new GameObject("LayerParent").transform;
            layers[i] = layer;
            layer.parent = transform;
            layer.position = originLayers[i].position;

            originLayers[i].transform.parent = layer;

            // 在前后各复制一份 
            Instantiate(originLayers[i].gameObject,
            originLayers[i].position + Vector3.right * bkLength, Quaternion.identity, layer);

            Instantiate(originLayers[i].gameObject,
            originLayers[i].position + Vector3.left * bkLength, Quaternion.identity, layer);
        }

        // 自动设置层级的滚动速度,也可以自行修改
        if (parallaxEffect.Length == 0)
        {
    
    
            parallaxEffect = new float[layers.Length];
            for (int i = 0; i < layers.Length; i++)
            {
    
    
                // 这里顺序是从前景到后景  
                parallaxEffect[i] = 1 - (float)(i * 0.8) / (layers.Length - 1);
            }
        }
    }

    private void Update()
    {
    
    
        for (int i = 0; i < layers.Length; i++)
        {
    
    

            // 背景和摄像机一起动
            float distanceMove = cam.transform.position.x * parallaxEffect[i];
            float distanceMoved = cam.transform.position.x * (1 - parallaxEffect[i]);

            layers[i].position = new Vector3(xPosition + distanceMove, layers[i].position.y);

            if (distanceMoved > xPosition + bkLength)
            {
    
    
                xPosition += bkLength;
            }
            else if (distanceMoved < xPosition - bkLength)
            {
    
    
                xPosition -= bkLength;
            }
        }
    }
}