70 lines
2.5 KiB
C#
70 lines
2.5 KiB
C#
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// Y-Sort 排序器 —— 根据物体的Z坐标(世界空间)动态调整Sprite的sortingOrder。
|
||
///
|
||
/// 原理:
|
||
/// 在2.5D等距视角游戏中,摄像机从斜上方45°俯视,Z坐标代表"前后"关系。
|
||
/// Z值越大(离相机越远=越靠前),sortingOrder越大,会遮挡Z值小的物体。
|
||
///
|
||
/// 用法:
|
||
/// 1. 挂到所有需要参与排序的Sprite物体上(玩家、敌人、树木、石头等)
|
||
/// 2. 设置 baseSortingOrder 区分不同类型的物体(如地面=0,角色=1000)
|
||
/// 3. 确保所有参与排序的Sprite在同一个Sorting Layer上
|
||
///
|
||
/// 注意:
|
||
/// - 本脚本假设摄像机从斜上方俯视(Z轴代表前后)
|
||
/// - 所有参与排序的物体必须在同一个Sorting Layer
|
||
/// </summary>
|
||
public class YSorter : MonoBehaviour
|
||
{
|
||
[Tooltip("基础排序值,用于区分不同类型的物体(如地面=0,角色=1000)")]
|
||
[SerializeField] private int baseSortingOrder = 0;
|
||
|
||
[Tooltip("Z坐标到sortingOrder的缩放系数(值越大,前后物体排序差异越明显)")]
|
||
[SerializeField] private float scaleFactor = 100f;
|
||
|
||
[Tooltip("是否每帧更新(关闭则只在移动时更新,性能更好)")]
|
||
[SerializeField] private bool updateEveryFrame = true;
|
||
|
||
private SpriteRenderer _spriteRenderer;
|
||
private Vector3 _lastPosition;
|
||
|
||
private void Awake()
|
||
{
|
||
_spriteRenderer = GetComponentInChildren<SpriteRenderer>();
|
||
if (_spriteRenderer == null)
|
||
{
|
||
Debug.LogWarning($"YSorter: 物体 {gameObject.name} 没有找到SpriteRenderer组件");
|
||
}
|
||
_lastPosition = transform.position;
|
||
}
|
||
|
||
private void LateUpdate()
|
||
{
|
||
if (_spriteRenderer == null) return;
|
||
|
||
// 如果设置了不是每帧更新,只在位置改变时更新
|
||
if (!updateEveryFrame && transform.position == _lastPosition)
|
||
return;
|
||
|
||
UpdateSortingOrder();
|
||
_lastPosition = transform.position;
|
||
}
|
||
|
||
private void UpdateSortingOrder()
|
||
{
|
||
// 使用物体中心(transform.position)的Z坐标作为排序依据
|
||
// 这样物品中心在地面上方时,会正确遮挡地面
|
||
float sortZ = transform.position.z;
|
||
|
||
// Z值越大(离相机越远),sortingOrder越大
|
||
int sortingOrder = baseSortingOrder + Mathf.RoundToInt(sortZ * scaleFactor);
|
||
|
||
if (_spriteRenderer.sortingOrder != sortingOrder)
|
||
{
|
||
_spriteRenderer.sortingOrder = sortingOrder;
|
||
}
|
||
}
|
||
}
|