492 武将登场-客户端 主键界面右侧按钮 支持指定某个入口固定放在某个固定位置,以及多个入口竞争同一个固定位置
4个文件已添加
207 ■■■■■ 已修改文件
Main/System/Main/HomeGridLayout.cs 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeGridLayout.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeGridLayoutCell.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeGridLayoutCell.cs.meta 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Main/System/Main/HomeGridLayout.cs
New file
@@ -0,0 +1,144 @@
using UnityEngine;
using System.Collections.Generic;
[ExecuteAlways]
[RequireComponent(typeof(RectTransform))]
public class HomeGridLayout : MonoBehaviour
{
    public RectOffset padding = new RectOffset();      // 边距
    public Vector2 cellSize = new Vector2(100f, 100f); // 单元格大小
    public Vector2 spacing = new Vector2(10f, 10f);    // 元素间距
    public int rows = 7; // 固定行数
    private void OnRectTransformDimensionsChange() => UpdateLayout();
    private void OnTransformChildrenChanged() => UpdateLayout();
#if UNITY_EDITOR
    private void Update()
    {
        if (!Application.isPlaying) UpdateLayout();
    }
#endif
    public void UpdateLayout()
    {
        if (rows <= 0 || transform.childCount == 0) return;
        List<RectTransform> flowChildren = new List<RectTransform>();
        List<RectTransform> fixedChildren = new List<RectTransform>();
        // 1. 遍历收集并分类所有激活的子物体
        for (int i = 0; i < transform.childCount; i++)
        {
            RectTransform child = transform.GetChild(i) as RectTransform;
            if (child == null || !child.gameObject.activeSelf) continue;
            HomeGridLayoutCell cell = child.GetComponent<HomeGridLayoutCell>();
            if (cell != null && cell.isFixedPosition)
                fixedChildren.Add(child);
            else
                flowChildren.Add(child);
        }
        // 2. 排序流动物体 (按 sortIndex)
        flowChildren.Sort((a, b) =>
        {
            var cellA = a.GetComponent<HomeGridLayoutCell>();
            var cellB = b.GetComponent<HomeGridLayoutCell>();
            int indexA = cellA != null ? cellA.sortIndex : int.MaxValue;
            int indexB = cellB != null ? cellB.sortIndex : int.MaxValue;
            return indexA.CompareTo(indexB);
        });
        // 3. 排序固定物体 (优先 sortIndex,其次 subSortIndex)
        fixedChildren.Sort((a, b) =>
        {
            var cellA = a.GetComponent<HomeGridLayoutCell>();
            var cellB = b.GetComponent<HomeGridLayoutCell>();
            int sortA = cellA != null ? cellA.sortIndex : int.MaxValue;
            int sortB = cellB != null ? cellB.sortIndex : int.MaxValue;
            if (sortA != sortB) return sortA.CompareTo(sortB);
            int subA = cellA != null ? cellA.subSortIndex : int.MaxValue;
            int subB = cellB != null ? cellB.subSortIndex : int.MaxValue;
            return subA.CompareTo(subB);
        });
        // 4. 开始分配网格 (核心优化部分)
        int currentGridIndex = 0; // 当前推演到的真实网格坑位
        int flowIndex = 0;
        int fixedIndex = 0;
        int totalValidChildren = flowChildren.Count + fixedChildren.Count;
        for (int i = 0; i < totalValidChildren; i++)
        {
            RectTransform targetChild = null;
            HomeGridLayoutCell nextFixedCell = null;
            if (fixedIndex < fixedChildren.Count)
            {
                nextFixedCell = fixedChildren[fixedIndex].GetComponent<HomeGridLayoutCell>();
            }
            // 分支 A:固定物体已经到了它期望的网格位置(或已经被前面的元素挤到了当前位置)
            if (nextFixedCell != null && nextFixedCell.sortIndex <= currentGridIndex)
            {
                targetChild = fixedChildren[fixedIndex];
                fixedIndex++;
            }
            // 分支 B:当前位置没有固定物体抢占,且还有流动物体排队,让流动物体填补空缺
            else if (flowIndex < flowChildren.Count)
            {
                targetChild = flowChildren[flowIndex];
                flowIndex++;
            }
            // 分支 C:没有流动物体填补空缺了,直接让网格索引“快进”到下一个固定物体的位置
            else if (nextFixedCell != null)
            {
                currentGridIndex = nextFixedCell.sortIndex; // 快进跳过中间的所有空白格子
                targetChild = fixedChildren[fixedIndex];
                fixedIndex++;
            }
            // 应用计算好的网格坐标
            if (targetChild != null)
            {
                SetChildTransform(targetChild, currentGridIndex);
                currentGridIndex++; // 占位成功,坑位后移
            }
        }
    }
   /// <summary>
    /// 将子物体放置到指定的网格索引位置
    /// </summary>
    private void SetChildTransform(RectTransform child, int gridIndex)
    {
        int col = gridIndex / rows;
        int row = gridIndex % rows;
        // 1. 先计算出如果轴心在右上角时的理论边缘坐标
        float edgeXPos = -padding.right - col * (cellSize.x + spacing.x);
        float edgeYPos = -padding.top - row * (cellSize.y + spacing.y);
        // 2. 为了消除团队潜规则,我们将格子的轴心改回正中心 (0.5, 0.5)
        // 因此实际坐标需要向左、向下再偏移半个单元格的大小
        float centerXPos = edgeXPos - (cellSize.x * 0.5f);
        float centerYPos = edgeYPos - (cellSize.y * 0.5f);
        // 统一锚点为右上角 (1, 1)
        child.anchorMin = new Vector2(1, 1);
        child.anchorMax = new Vector2(1, 1);
        // 轴心(Pivot)改为正中心!
        child.pivot = new Vector2(0.5f, 0.5f);
        child.sizeDelta = cellSize;
        // 赋予中心坐标
        child.anchoredPosition = new Vector2(centerXPos, centerYPos);
    }
}
Main/System/Main/HomeGridLayout.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b7ec546648dc7bc4297af70316bca133
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant:
Main/System/Main/HomeGridLayoutCell.cs
New file
@@ -0,0 +1,41 @@
using UnityEngine;
public class HomeGridLayoutCell : MonoBehaviour
{
    [Header("模式")]
    [Tooltip("勾选则固定在目标格子上占位;不勾则作为流水元素自动填空。")]
    public bool isFixedPosition;
    [Header("排序")]
    [Tooltip("决定固定元素的所在格子,或流水元素的出场顺序(注意从0开始计)。")]
    public int sortIndex;
    [Tooltip("当多个元素抢占同一个格子或排序相同时,该值越小越优先。")]
    public int subSortIndex;
    private void OnEnable()
    {
        NotifyParentToUpdate();
    }
    private void OnDisable()
    {
        NotifyParentToUpdate();
    }
    /// <summary>
    /// 通知父级的网格脚本重新排版
    /// </summary>
    private void NotifyParentToUpdate()
    {
        // 如果物体被销毁或者没有父级了,就不管了
        if (transform.parent == null)
            return;
        HomeGridLayout layout = transform.parent.GetComponent<HomeGridLayout>();
        if (layout != null)
        {
            layout.UpdateLayout();
        }
    }
}
Main/System/Main/HomeGridLayoutCell.cs.meta
New file
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 28e84dc55c523d64bbeb2631a3355c73
MonoImporter:
  externalObjects: {}
  serializedVersion: 2
  defaultReferences: []
  executionOrder: 0
  icon: {instanceID: 0}
  userData:
  assetBundleName:
  assetBundleVariant: