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

复刻经典Snake游戏:MoveTowards与OnTriggerEnter2D异常问题

经典Snake游戏复刻的两个技术问题排查与解决

问题1:Vector3.MoveTowards函数未正常工作(蛇身无法正确跟随玩家)

核心原因

蛇身跟随逻辑存在设计错误:所有蛇身都直接追逐玩家的当前位置,而非经典Snake游戏中“链式跟随”(每个蛇身追逐前一个身体部位位置)的标准逻辑。此外还有两个细节问题放大了异常:

  • 蛇身移动速度(Speed = 4)低于玩家速度(snakeSpeed = 5),导致蛇身永远无法追上玩家,看起来像是MoveTowards失效。
  • 虽然snakePosition的赋值时机(先移动玩家再更新位置)逻辑正确,但由于整体跟随逻辑错误,导致最终效果异常。

解决方法

实现正确的链式跟随逻辑,维护蛇身部位队列,让每个蛇身追踪前一个部位的位置:

  1. 在SnakeMovement中添加列表存储所有蛇身对象:
public List<Transform> snakeBodyParts = new List<Transform>();
  1. 修改生成蛇身的代码,将新蛇身加入列表:
// 替换原Instantiate代码段
GameObject newBody = Instantiate(snakeBody, spawnPosition, transform.rotation);
snakeBodyParts.Add(newBody.transform);
  1. 重写ChaseSnake脚本,让蛇身追踪指定目标(而非固定追踪玩家):
using UnityEngine;

public class ChaseSnake : MonoBehaviour
{
    private Transform target;
    [SerializeField] private float speed = 5f; // 设为与玩家速度一致或略高

    public void SetTarget(Transform newTarget)
    {
        target = newTarget;
    }

    void Update()
    {
        if (target != null)
        {
            transform.position = Vector3.MoveTowards(transform.position, target.position, speed * Time.deltaTime);
        }
    }
}
  1. 在SnakeMovement中,为新生成的蛇身设置追踪目标:
// 生成新蛇身后添加
ChaseSnake chaseScript = newBody.GetComponent<ChaseSnake>();
if (snakeBodyParts.Count == 1)
{
    // 第一个蛇身追踪玩家
    chaseScript.SetTarget(transform);
}
else
{
    // 后续蛇身追踪前一个蛇身部位
    chaseScript.SetTarget(snakeBodyParts[snakeBodyParts.Count - 2]);
}

问题2:生成snakeBody时,蛇与蛇身未靠近却触发碰撞

核心原因

  1. 蛇身生成位置逻辑错误:初始Distance = 10被直接用作世界坐标偏移量,且每次吃食物都累加Distance,导致生成的蛇身距离玩家越来越远,蛇身向玩家移动时极易触发碰撞;同时生成位置的方向计算未贴合蛇身链式排列的需求。
  2. 未销毁食物对象:玩家碰撞食物后未销毁食物,若食物的Collider为Trigger,可能与新生成的蛇身触发碰撞,被误判为蛇身碰撞。
  3. 碰撞检测无初始化过滤:蛇身生成时若因位置误差与玩家Collider重叠,会直接触发死亡逻辑。

解决方法

  1. 修正蛇身生成位置逻辑:改为基于移动方向的链式排列,使用固定间距生成蛇身:
// 替换原生成蛇身的多分支代码
// 先获取当前移动方向
Vector3 moveDirection = Vector3.zero;
if (up) moveDirection = Vector3.up;
else if (down) moveDirection = Vector3.down;
else if (right) moveDirection = Vector3.right;
else if (left) moveDirection = Vector3.left;

// 固定蛇身间距(根据Sprite大小调整,示例为1单位)
float bodySpacing = 1f;
// 生成在玩家后方,与最后一个部位保持固定间距
Vector3 spawnPosition = transform.position - moveDirection * bodySpacing * (snakeBodyParts.Count + 1);

GameObject newBody = Instantiate(snakeBody, spawnPosition, transform.rotation);
snakeBodyParts.Add(newBody.transform);
  1. 碰撞食物后销毁食物:在每个食物碰撞分支中添加销毁代码:
if (up == true && collision.gameObject.tag == "Food")
{
    // ... 原生成蛇身代码
    Destroy(collision.gameObject); // 添加此行
}
// 其他方向的食物碰撞逻辑同理添加
  1. 过滤初始化阶段的碰撞:生成蛇身时暂时禁用其Collider,延迟一帧后启用:
// 生成新蛇身后添加
Collider2D bodyCollider = newBody.GetComponent<Collider2D>();
bodyCollider.enabled = false;
StartCoroutine(EnableColliderAfterFrame(bodyCollider));

// 在SnakeMovement中新增协程函数
private IEnumerator EnableColliderAfterFrame(Collider2D collider)
{
    yield return null;
    collider.enabled = true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:47:34