You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity C#可移动网格系统Move函数实现异常求助

体素游戏可移动网格系统Move函数实现问题

正在为体素游戏开发可移动网格系统,大部分功能已完成,但Move函数的实现一直受阻。以下是未实现Move函数逻辑的核心代码:

using UnityEngine;
using System;

public class Grid<T>
{
    private T[] data;
    public Vector3Int position;
    public Vector3Int size;
    public int iSize;

    public Grid(Vector3Int size)
    {
        this.position = new Vector3Int(0, 0, 0);
        this.size = size;
        this.iSize = size.x * size.y * size.z;
        this.data = new T[size.x * size.y * size.z];
    }

    public T this[int x, int y, int z]
    {
        get
        {
            Vector3Int position = new Vector3Int(x, y, z);
            if (!IsValidIndex(position - this.position))
            {
                throw new IndexOutOfRangeException("Invalid position");
            }

            Vector3Int positionRelative = PositionToRelative(position);
            return this.data[VectorToIndex(positionRelative)];
        }
        set
        {
            Vector3Int position = new Vector3Int(x, y, z);
            if (!IsValidIndex(position - this.position))
            {
                throw new IndexOutOfRangeException("Invalid position");
            }

            Vector3Int positionRelative = PositionToRelative(position);
            this.data[VectorToIndex(positionRelative)] = value;
        }
    }

    public void Move(Vector3Int newPosition)
    {
        Vector3Int offset = PositionToRelative(newPosition);
        T[] newData = new T[data.Length];

        this.data = newData;
        this.position = newPosition;
    }

    private bool IsPositionInRange(Vector3Int position, Vector3Int start, Vector3Int end)
    {
        int minX = Mathf.Min(start.x, end.x);
        int maxX = Mathf.Max(start.x, end.x);
        int minY = Mathf.Min(start.y, end.y);
        int maxY = Mathf.Max(start.y, end.y);
        int minZ = Mathf.Min(start.z, end.z);
        int maxZ = Mathf.Max(start.z, end.z);
        return position.x >= minX
            && position.x <= maxX
            && position.y >= minY
            && position.y <= maxY
            && position.z >= minZ
            && position.z <= maxZ;
    }

    private Vector3Int PositionToRelative(Vector3Int position)
    {
        return position - this.position;
    }

    private bool IsValidIndex(Vector3Int position)
    {
        int index = VectorToIndex(position);

        return index >= 0 && index < this.iSize;
    }

    private bool IsValidIndex(int index)
    {
        return index >= 0 && index < this.iSize;
    }

    private int VectorToIndex(Vector3Int position)
    {
        return position.x + this.size.x * (position.y + this.size.y * position.z);
    }
}

测试代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tester : MonoBehaviour
{
    void PrintMatrix<T>(Grid<T> grid)
    {
        for (int x = 0; x < grid.size.x; x++)
        {
            string output = "\n";

            for (int y = 0; y < grid.size.y; y++)
            {
                Vector3Int position = new Vector3Int(x, y, 0) + grid.position;
                output += grid[position.x, position.y, position.z];

                if (y < grid.size.y - 1)
                {
                    output += " ";
                }
            }

            Debug.Log(output);
        }
    }

    void Start()
    {
        Vector3Int size = new Vector3Int(4, 4, 1);
        Grid<int> grid = new Grid<int>(size);

        for (int x = 0; x < size.x; x++)
        {
            for (int y = 0; y < size.y; y++)
            {
                grid[x, y, 0] = x + size.y * y + 1;
            }
        }

        PrintMatrix<int>(grid);

        Debug.Log("-------- Amogus ------------");

        grid.Move(new Vector3Int(-1, 0, 0));

        PrintMatrix<int>(grid);
    }

    void Update() { }
}

示例中尝试将网格左移,首次输出的网格数据正确:

1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16

但执行Move函数后输出结果不符合预期:

预期输出:

0 1 5 9
0 2 6 10
0 3 7 11
0 4 8 12

实际输出:

2 6 10 14
3 7 11 15
4 8 12 16
0 9 13 0

曾尝试过以下Move函数实现,但仍无法正确计算startPosition和endPosition,导致功能异常:

public void Move(Vector3Int position)
{
    T[] newData = new T[data.Length];
    Vector3Int positionRelative = PositionToRelative(position);

    Vector3Int startPosition = new Vector3Int(
        positionRelative.x >= 0 ? positionRelative.x : this.size.x + positionRelative.x,
        positionRelative.y >= 0 ? positionRelative.y : this.size.y + positionRelative.y,
        positionRelative.z >= 0 ? positionRelative.z : this.size.z + positionRelative.z
    );
    Vector3Int endPosition = new Vector3Int(
        positionRelative.x < 0 ? this.size.x : positionRelative.x,
        positionRelative.y < 0 ? this.size.y : positionRelative.y,
        positionRelative.z < 0 ? this.size.z : positionRelative.z
    );

    Debug.Log(positionRelative + " " + startPosition + " " + endPosition);

    for (int x = 0; x < size.x; x++)
    {
        for (int y = 0; y < size.y; y++)
        {
            for (int z = 0; z < size.z; z++)
            {
                Vector3Int currentPosition = new Vector3Int(x, y, z);
                int index = VectorToIndex(currentPosition);
                int translationIndex = VectorToIndex(currentPosition - positionRelative);

                if (
                    IsPositionInRange(currentPosition, startPosition, endPosition)
                    || !IsValidIndex(translationIndex)
                )
                {
                    newData[index] = default(T);
                    continue;
                }

                newData[index] = data[translationIndex];
            }
        }
    }

    this.position = position;
    data = newData;
}

预期效果说明:位置为(0,0,0)的网格展示了其2x2区域的样子,位置为(-1,0,0)的网格则展示了移位后2x2区域的预期效果,新露出的区域用0表示未知值。

内容的提问来源于stack exchange,提问作者Bloxxy 213

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:52:45