? 效果如下
在許多游戲、APP 或動效頁面中,我們常見的一種視覺效果是 視差滾動(Parallax Scrolling):前景、中景、背景在鼠標或設備移動時以不同速率輕微移動,從而營造出一種空間感和深度感。
目前遇到這樣一個需求 所以在?Unity 中實現一個支持鼠標控制、陀螺儀控制和腳本控制的 UI 視差腳本,并提供完整源碼、注釋及使用方法,適合用于啟動頁、主菜單、信息卡片界面等多種場景。
🧠 實現原理
核心思想是:
每個 UI 圖層記錄起始位置;
根據輸入設備(鼠標或陀螺儀),獲取目標參考位置(通常是屏幕坐標歸一化到
[0,1]
);用
Lerp
緩動插值方式移動 UI 圖層,使其偏移方向和輸入方向一致;每個圖層的移動速度和最大移動范圍可以獨立配置。
📦 腳本結構概述
我們將視差系統封裝為一個 MonoBehaviour 腳本,名為 MMParallaxUI
,結構清晰、易于擴展:
名稱 | 說明 |
---|---|
ParallaxLayer | 子類,表示每一層的參數設置(RectTransform、速度、幅度、是否啟用等) |
Modes | 視差控制模式(鼠標 / 陀螺儀 / 腳本) |
ParallaxLayers | 圖層列表,可在 Inspector 中直接配置 |
AmplitudeMultiplier | 所有圖層的幅度乘數 |
SpeedMultiplier | 所有圖層的速度乘數 |
🧩 完整源碼(含中文注釋)
using System;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 用于實現UI視差滾動效果的組件(Parallax)
/// 支持鼠標控制、陀螺儀控制(移動端)、或通過代碼控制
/// </summary>
public class MMParallaxUI : MonoBehaviour
{/// <summary>/// 用于存儲每個視差圖層的設置/// </summary>[Serializable]public class ParallaxLayer{[Tooltip("該圖層的 RectTransform 組件")]public RectTransform Rect;[Tooltip("該圖層移動的速度")]public float Speed = 2f;[Tooltip("該圖層相對初始位置最大移動距離(幅度)")]public float Amplitude = 50f;[HideInInspector]public Vector2 StartPosition; // 圖層的初始位置(運行時記錄)[Tooltip("是否啟用該圖層的視差效果")]public bool Active = true;}/// <summary>/// 控制視差輸入的模式類型/// </summary>public enum Modes{Mouse, // 使用鼠標位置控制(適用于PC)Gyroscope, // 使用陀螺儀控制(適用于移動設備)Script // 外部腳本通過 SetReferencePosition 控制}[Header("基礎設置")][Tooltip("當前使用的控制模式")]public Modes Mode = Modes.Mouse;[Tooltip("控制所有圖層振幅的倍率")]public float AmplitudeMultiplier = 1f;[Tooltip("控制所有圖層速度的倍率")]public float SpeedMultiplier = 1f;[Tooltip("參與視差移動的圖層列表")]public List<ParallaxLayer> ParallaxLayers;// 內部變量protected Vector2 _referencePosition; // 當前輸入參考位置(歸一化)protected Vector3 _newPosition; // 圖層的新位置protected Vector2 _mousePosition; // 鼠標當前位置(屏幕坐標)/// <summary>/// Start 時初始化所有圖層的起始位置/// </summary>protected virtual void Start(){Initialization();}/// <summary>/// 初始化:記錄每個圖層的起始位置/// </summary>public virtual void Initialization(){foreach (ParallaxLayer layer in ParallaxLayers){if (layer.Rect != null){layer.StartPosition = layer.Rect.position;}}}/// <summary>/// 每幀更新:移動所有圖層/// </summary>protected virtual void Update(){MoveLayers();}/// <summary>/// 根據控制模式更新 _referencePosition 并移動圖層/// </summary>protected virtual void MoveLayers(){// 根據控制模式獲取輸入switch (Mode){case Modes.Gyroscope:// 示例:你可以接入 Input.gyro.rotationRate 或 attitude(僅限移動設備)// _referencePosition = new Vector2(Input.gyro.rotationRate.x, Input.gyro.rotationRate.y);break;case Modes.Mouse:
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER_mousePosition = UnityEngine.InputSystem.Mouse.current.position.ReadValue(); // 新輸入系統
#else_mousePosition = Input.mousePosition; // 舊輸入系統
#endif// 將鼠標屏幕坐標轉為歸一化視口坐標(0~1)_referencePosition = Camera.main.ScreenToViewportPoint(_mousePosition);break;case Modes.Script:// 由外部通過 SetReferencePosition() 設置break;}// 遍歷每個圖層并移動位置foreach (ParallaxLayer layer in ParallaxLayers){if (layer.Active && layer.Rect != null){// X軸移動(緩動)_newPosition.x = Mathf.Lerp(layer.Rect.position.x,layer.StartPosition.x + _referencePosition.x * layer.Amplitude * AmplitudeMultiplier,layer.Speed * SpeedMultiplier * Time.deltaTime);// Y軸移動(緩動)_newPosition.y = Mathf.Lerp(layer.Rect.position.y,layer.StartPosition.y + _referencePosition.y * layer.Amplitude * AmplitudeMultiplier,layer.Speed * SpeedMultiplier * Time.deltaTime);_newPosition.z = 0f;// 更新圖層位置layer.Rect.position = _newPosition;}}}/// <summary>/// 設置一個新的輸入參考位置(僅在 Script 模式下使用)/// 值通常在 (0,0) 到 (1,1) 之間/// </summary>public virtual void SetReferencePosition(Vector3 newReferencePosition){_referencePosition = newReferencePosition;}
}
🛠? 使用方法
1?? 添加組件
在 Canvas 下創建一個空 GameObject,命名為
UIParallaxRoot
。掛載
MMParallaxUI
腳本。在 Inspector 中配置
ParallaxLayers
列表,添加你希望參與視差效果的圖層(Image/Text 等 UI 元素)。配置每層的
Speed
和Amplitude
。
2?? 設置控制模式
Mouse
(默認):使用鼠標位置控制(適用于PC)。Gyroscope
:適用于移動端,可擴展為接入Input.gyro
。Script
:通過代碼調用SetReferencePosition()
控制。
// 示例:手動控制參考位置
parallaxUI.SetReferencePosition(new Vector2(0.5f, 0.5f)); // 回中
🎮 目前我使用的閾值如下
👇 均為透明png實現
按我這個閾值去配置? 可以得到首圖的效果
這個腳本目前直接掛載使用即可,陀螺儀方面還未拖拽完畢,也可以增加“自動回中”邏輯,在鼠標或輸入松開后回歸中心位置。如需圖片素材做參考,或者你有新的思路和實現方式 可以私信我或在評論區留言。