UMiniGame/Assets/Games/Scripts/ScrollingBackground.cs
2025-12-27 15:29:20 +08:00

134 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 挂载在Canvas上控制两个背景Image从上往下无限滚动适配实际屏幕高度间隔
/// </summary>
[RequireComponent(typeof(Canvas))]
//[ExecuteInEditMode]
public class BackgroundScroll : MonoBehaviour
{
[Header("滚动速度(像素/秒)")]
public float scrollSpeed = 50f;
[Header("是否自动获取子物体的两个Image取消则手动指定")]
public bool autoGetImages = true;
[Header("手动指定的两个背景ImageautoGetImages为false时生效")]
public Image bgImage1;
public Image bgImage2;
// Image的RectTransform组件
private RectTransform rt1;
private RectTransform rt2;
// Image在屏幕上的实际显示高度关键适配Aspect缩放
private float actualImageHeight;
private float rt1ScaleY = 1;
void Start()
{
}
private void OnEnable()
{
// 初始化Image和RectTransform
InitImages();
// 计算Image的实际屏幕高度适配Aspect模式
if (rt1 != null)
{
actualImageHeight = GetImageActualHeight(rt1);
rt1ScaleY = rt1.localScale.y;
// 初始化第二个Image的位置在第一个Image顶部上方间隔实际屏幕高度
rt2.anchoredPosition = new Vector2(0, rt1.anchoredPosition.y + actualImageHeight);
//Debug.Log($"图片实际屏幕高度:{actualImageHeight},已初始化第二张图位置");
}
else
{
Debug.LogError("未找到有效的背景Image请检查Canvas下的子物体或手动指定Image");
}
}
void Update()
{
if (rt1 == null || rt2 == null) return;
if (rt1ScaleY != rt1.localScale.y)
{
actualImageHeight = GetImageActualHeight(rt1);
rt2.anchoredPosition = new Vector2(0, rt1.anchoredPosition.y + actualImageHeight);
rt1ScaleY = rt1.localScale.y;
}
// 让两个Image向下滚动anchoredPosition的y轴减小
rt1.anchoredPosition -= new Vector2(0, scrollSpeed * Time.deltaTime);
rt2.anchoredPosition -= new Vector2(0, scrollSpeed * Time.deltaTime);
// 检测第一个Image是否完全滚出屏幕下方重置位置用实际高度判断
if (rt1.anchoredPosition.y <= -actualImageHeight)
{
rt1.anchoredPosition = new Vector2(0, rt2.anchoredPosition.y + actualImageHeight);
}
// 检测第二个Image是否完全滚出屏幕下方重置位置用实际高度判断
if (rt2.anchoredPosition.y <= -actualImageHeight)
{
rt2.anchoredPosition = new Vector2(0, rt1.anchoredPosition.y + actualImageHeight);
}
}
/// <summary>
/// 初始化Image组件和RectTransform
/// </summary>
private void InitImages()
{
if (autoGetImages)
{
Image[] images = GetComponentsInChildren<Image>();
if (images.Length >= 2)
{
bgImage1 = images[0];
bgImage2 = images[1];
}
else
{
Debug.LogError("Canvas下的Image数量不足2个请检查");
return;
}
}
if (bgImage1 != null) rt1 = bgImage1.GetComponent<RectTransform>();
if (bgImage2 != null) rt2 = bgImage2.GetComponent<RectTransform>();
}
/// <summary>
/// 计算RectTransform在屏幕上的实际显示高度适配Aspect缩放
/// </summary>
/// <param name="rt">目标RectTransform</param>
/// <returns>实际屏幕高度(像素)</returns>
private float GetImageActualHeight(RectTransform rt)
{
// 获取RectTransform的世界空间包围盒
//Bounds bounds = RectTransformUtility.CalculateRelativeRectTransformBounds(transform, rt);
// 转换为屏幕空间的高度考虑Canvas的缩放
//float canvasScale = GetComponent<Canvas>().scaleFactor;
return rt.sizeDelta.y * rt.localScale.y;
}
///// <summary>
///// 编辑器下实时预览(可选)
///// </summary>
//private void OnDrawGizmos()
//{
// if (Application.isPlaying) return;
// InitImages();
// if (rt1 != null)
// {
// actualImageHeight = GetImageActualHeight(rt1);
// if (rt2 != null)
// {
// rt2.anchoredPosition = new Vector2(0, actualImageHeight);
// }
// }
//}
}