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

求助:如何正确冻结脚本实例化Prefab触碰玩家后的X轴位置?

问题根源

你代码里的核心问题是静态变量的错误使用:Block_Movement中的rb是静态变量,它属于类本身而非单个方块实例。调用静态的stopMovement()时,只会操作最后一个初始化的方块的Rigidbody,而非所有已生成的实例。你误以为冻结了Prefab原文件,实际上是静态变量的特性导致操作对象不符合预期。

修复方案

1. 重构Block_Movement脚本

把静态变量改成实例变量,同时用静态列表追踪所有存活的方块,实现批量停止:

public class Block_Movement : MonoBehaviour
{
    // 每个方块自己的Rigidbody(实例变量)
    private Rigidbody rb;
    public int speed;

    // 静态列表存所有存活的方块实例
    private static List<Block_Movement> allBlocks = new List<Block_Movement>();

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
        allBlocks.Add(this);
    }

    void FixedUpdate()
    {
        rb.AddForce(-speed * Time.deltaTime, 0, 0);
    }

    // 停止单个方块的实例方法
    public void StopSingleBlock()
    {
        rb.constraints = RigidbodyConstraints.FreezePosition;
    }

    // 停止所有方块的静态方法
    public static void StopAllBlocks()
    {
        print("All blocks stopped");
        foreach (var block in allBlocks)
        {
            block.StopSingleBlock();
        }
        allBlocks.Clear();
    }

    private void OnDestroy()
    {
        // 方块销毁时从列表移除,避免空引用
        allBlocks.Remove(this);
    }
}

2. 修改碰撞检测脚本的调用逻辑

把原来的Block_Movement.stopMovement()换成新的批量停止方法:

private void OnCollisionEnter(Collision block)
{
    if (block.gameObject.CompareTag("Blocks"))
    {
        Timer_Script.stopTimer();
        Block_Spawner.gameOver = true;
        Block_Movement.StopAllBlocks();
    }
}

额外优化提示

  • 用CompareTag()替代Equals(),Unity官方推荐,性能更优且能避免空引用问题
  • 现在每个方块的Rigidbody都是独立控制的,不会再出现“误操作Prefab”的错觉(实际上你之前并没有修改到Prefab,只是静态变量导致操作对象不对)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:01:18