Unity重构破碎墙体脚本后移动功能失效求助
咱们先理清楚你遇到的问题:原来的代码里立方体正常移动,但把_WallMovement.initializeMovement()拆到独立的wallMoving()函数后,立方体就不动了,只有在wallMoving()里重新写indizes[0] = x才会部分生效,而且控制台没报错。
核心原因:数组是引用类型,你不小心共享了同一个数组实例
你在newWallMovement()里用的是同一个indizes数组,然后把它赋值给每个WallMovement组件。因为数组是引用类型,所有组件的indizes字段其实指向的是内存里的同一个数组。
当newWallMovement()的循环结束后,这个数组里的x值已经变成了循环的最后一个值(也就是oldWallsizeX-2)。等你在wallMoving()里调用initializeMovement()时,所有立方体拿到的都是这个最后一次循环的x值,自然不会执行正确的移动逻辑。
而当你在wallMoving()里重新加indizes[0] = x时,只有当前循环的x对应的那一批立方体的数组值被临时修改,所以才会部分生效——但这依然是共享数组的问题,不是正确的解决方式。
修复方案:给每个立方体分配独立的数组(或简化数据结构)
这里有两种更可靠的修复方式,你可以选适合自己的:
方案1:为每个立方体创建独立的数组实例
修改newWallMovement(),每次循环都新建一个数组,这样每个WallMovement拿到的都是属于自己的数组,不会被后续循环覆盖:
void newWallMovement() { for (int x = 1; x < oldWallsizeX-1; x++) { for (int y = 0; y < oldWallsizeY; y++) { for (int z = 0; z < oldWallsizeZ; z++) { // 为当前立方体创建专属数组 int[] cubeIndizes = new int[3]; cubeIndizes[0] = x; cubeIndizes[1] = y; cubeIndizes[2] = z; newWall = wallSegments[x,y,z]; GameObject _wallSegment = newWall.gameObject; WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement>(); _WallMovement.indizes = cubeIndizes; } } } }
然后你的wallMoving()就可以保持原样,只需要遍历所有立方体调用initializeMovement()就行:
void wallMoving(){ for (int x = 1; x < oldWallsizeX-1; x++) { for (int y = 0; y < oldWallsizeY; y++) { for (int z = 0; z < oldWallsizeZ; z++) { newWall = wallSegments[x,y,z]; WallMovement _WallMovement = newWall.GetComponent<WallMovement>(); _WallMovement.initializeMovement(); } } } }
方案2:简化数据结构,避免使用数组(更推荐)
看你的WallMovement脚本,其实只用到了indizes[0](也就是x索引)来计算modulo,完全没必要用数组。咱们直接把indizes换成单独的字段,更清晰也不会有引用问题:
首先修改WallMovement脚本:
public class WallMovement : MonoBehaviour { public int xIndex; // 直接存储需要的x索引 int modulo; public void initializeMovement() { modulo = xIndex % 2; if (modulo > 0) { // 执行奇数x的移动逻辑 } else { // 执行偶数x的移动逻辑 } } }
然后修改newWallMovement()里的赋值逻辑:
void newWallMovement() { for (int x = 1; x < oldWallsizeX-1; x++) { for (int y = 0; y < oldWallsizeY; y++) { for (int z = 0; z < oldWallsizeZ; z++) { newWall = wallSegments[x,y,z]; WallMovement _WallMovement = newWall.GetComponent<WallMovement>(); _WallMovement.xIndex = x; // 直接赋值x索引 } } } }
这样不仅解决了问题,代码可读性也更高,还减少了不必要的数组操作。
额外优化:简化wallMoving()的遍历逻辑
你可以用foreach遍历wallSegments数组,避免重复嵌套循环,代码更简洁:
void wallMoving(){ foreach (Transform segment in wallSegments) { if (segment == null) continue; // 跳过空引用 WallMovement movement = segment.GetComponent<WallMovement>(); if (movement != null) { movement.initializeMovement(); } } }
这样不管数组的维度是多少,都能遍历到所有立方体,维护起来更方便。
内容的提问来源于stack exchange,提问作者ZenBreaker

