求助:如何正确冻结脚本实例化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
相关产品推荐
相关产品推荐

