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

Unity实现类Google Snake的平滑移动技术问询

蛇类游戏平滑移动实现问题

我正在开发一款蛇类游戏,没有使用单一色块,而是为蛇头、蛇身、转角和蛇尾分别使用不同精灵,目标是实现类似Google Snake的移动效果。

目前已完成移动、生长、转向生成转角等核心机制,蛇的移动基于抽象二维网格,整体由蛇节点链表组成:head <- body <- corner <- ... <- tail,节点继承关系如下:

class BaseNode; // BaseNode 仅处理四个方向的精灵
class SnakeNode: BaseNode;
class SnakeCorner: SnakeNode;
class SnakeHead: SnakeNode; // 单例
class SnakeTail: SnakeNode; // 单例

SnakeNode类的核心实现:

public class SnakeNode : BaseNode
{
    public SnakeNode prev;
    public SnakeNode next;
    public Vector2Int gridPos; // 抽象二维网格中的位置
    // 每个蛇节点都有自身的方向
    protected Vector2Int _direction;

    // SnakeCorner 会重写这个属性
    public virtual Vector2Int Direction
    {
        get => _direction;
        set
        {
         // ...
         // 切换方向时自动设置SpriteRenderer.Sprite的代码
        }
    }
}

已实现网格坐标转世界坐标的函数:

public Vector2 Grid2WorldPosition(int row, int col)
{
    var offset = new Vector2(setting.cols, setting.rows) / 2;

    return (new Vector2(col ,row) - offset) * setting.scale;
}

移动逻辑在MoveSnack函数中实现:

private BaseNode[,] gridMap;

private void MoveSnack() {
    var tail = SnackTail.Instance;
    var newTailPos = tail.prev.gridPos;
    var newTailDir = tail.prev.Direction;

    var head = SnackHead.Instance;
    var oldPos = head.gridPos;
    var newPos = head.gridPos + new Vector2Int(head.Direction.y, head.Direction.x);
    if (CheckOutOfBounds(newPos.x, newPos.y)) {
        // 边界限制相关代码
    }

    if (gridMap[newPos.x, newPos.y] != null) {
        // 吃苹果或碰撞处理代码
    }

    GameObject gameObj;
    if (head.Direction != head.next.Direction)
    {
        // 创建SnakeCorner对象的代码
    }
    else
    {
        // 创建普通SnakeNode对象的代码
    }
    var body = gameObj.GetComponent<SnackNode>();
    body.Direction = head.Direction;
    body.gridPos = oldPos;

    SnackListHandler.Insert(head, body);

    head.gridPos = newPos;

    // 更新抽象地图上的位置
    gridMap[newPos.x, newPos.y] = head;
    gridMap[oldPos.x, oldPos.y] = body;
    gridMap[tail.gridPos.x, tail.gridPos.y] = null;
    gridMap[newTailPos.x, newTailPos.y] = tail; 

    tail.Direction = newTailDir;
    tail.gridPos = newTailPos;

    // 仅更新头尾位置
    var nodes = new SnackNode[]{head, tail};
    foreach (var node in nodes) {
        node.transform.position = Grid2WorldPosition(node.gridPos.x, node.gridPos.y);
    }

    if (tail.prev != head)
        SnackListHandler.Remove(tail.prev);
}

SnackListHandler负责维护蛇节点的链表关系。当前运行MoveSnack函数时,蛇头和蛇尾会直接“跳跃”到新世界坐标,产生明显卡顿感。尝试过Lerp插值方法但未达到预期效果,寻求实现Google Snake式平滑移动的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:51:03