前言
虽然挺简单的,不过逛了一圈没看到,干脆分享下
核心逻辑就是给克隆每个子对象并生成对应的父对象,之后控制这些新父对象进行滚动
使用
将背景按顺序拖拽到同一父对象上,设定背景图层顺序,将脚本挂载到父级即可
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;
}
}
}
}