Unity-重构的崩溃墙脚本停止工作了吗? [英] Unity - Refactored crumbling wall script stops working?

查看:73
本文介绍了Unity-重构的崩溃墙脚本停止工作了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象,它立即被成千上万个小立方体替换,然后在初始化后开始一个接一个地移动.

I have an Object that gets replaced by thousands of little cubes at once, which then begin moving one after another after initialization.

我有可以运行的代码,但是当我尝试对其进行重构以将其清理时,它将停止工作.立方体不动.当我尝试将变量初始化和运动初始化分开时,会发生这种情况.

I have code that works, but when I try to refactor it to clean it up, it stops working. The cubes dont move. This happens when I try to separate the Variable Initialisation and the Movement Initialisation.

这是我的原始代码段,它可以正常工作:

public class WallCreation : MonoBehaviour {

    public Transform wallSegmentPrefab;
    GameObject oldWall;
    Vector3 oldWallSize;
    int oldWallsizeX;
    int oldWallsizeY;
    int oldWallsizeZ;
    Vector3 oldWallPosition;
    Vector3 oldWallCornerPosition;
    Transform newWall;
    Transform parentWallSegment;
    Transform[ , , ] wallSegments;
    int[] indizes;

void Start () { 
    indizes= new int[3];
}

public void newWallScript(){
    initializeNewWall ("zWall++");
    StartCoroutine (waitForMovement ());
}

void initializeNewWall(string replaceWall)
{
    oldWall = GameObject.Find(replaceWall);
    oldWallSize = oldWall.transform.localScale;
    oldWallPosition = oldWall.transform.localPosition;
    oldWallsizeX=(int) oldWallSize.x;
    oldWallsizeY=(int) oldWallSize.y;
    oldWallsizeZ=(int) oldWallSize.z;
    oldWallCornerPosition = oldWallPosition - oldWallSize / 2 + wallSegmentPrefab.localScale / 2;

    wallSegments = new Transform[oldWallsizeX , oldWallsizeY , oldWallsizeZ];

    for (int x = 0; x < oldWallsizeX; x++)
    {           
        for (int y = 0; y < oldWallsizeY; y++)
        {
            for (int z = 0; z < oldWallsizeZ; z++)
            {
                newWall = Instantiate(wallSegmentPrefab);

                GameObject _wallSegment = newWall.gameObject;
                _wallSegment.AddComponent<WallMovement> ();
                wallSegments[x,y,z] = newWall;
            }
        }
    }
    oldWall.SetActive(false);
}

void newWallMovement()
{
    for (int x = 1; x < oldWallsizeX-1; x++)
    {
        indizes [0] = x;                   
        for (int y = 0; y < oldWallsizeY; y++) 
        {
            indizes [1] = y;
            for (int z = 0; z < oldWallsizeZ; z++) {
                indizes[2] = z;

                newWall = wallSegments[x,y,z];
                GameObject _wallSegment = newWall.gameObject;
                WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement> ();
                _WallMovement.indizes = indizes;

                _WallMovement.initializeMovement ();

            }
        }
    }
}

IEnumerator waitForMovement()
{
    yield return new WaitForSeconds(1f);
    newWallMovement();
}

}

这是我改进的代码,无法使用,并且(...)保持不变:

public class WallCreation : MonoBehaviour {

//(...) 

public void newWallScript(){
    //(...)
    StartCoroutine (waitForMoving());
}

void initializeNewWall(string replaceWall)
{
    (...)
}

void newWallMovement()
{
    for (int x = 1; x < oldWallsizeX-1; x++)
    {
        indizes [0] = x;                   
        for (int y = 0; y < oldWallsizeY; y++) 
        {
            indizes [1] = y;
            for (int z = 0; z < oldWallsizeZ; z++) {
                indizes[2] = z;

                newWall = wallSegments[x,y,z];
                GameObject _wallSegment = newWall.gameObject;
                WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement> ();
                _WallMovement.indizes = indizes;

                //this is cut out and put into the wallMoving() void
                //_WallMovement.initializeMovement ();

            }
        }
    }
}

void wallMoving(){
    for (int x = 1; x < oldWallsizeX-1; x++)
    {
        //indizes [0] = x; //only with this enabled it works for some reason, otherwise it doesn't                    
        for (int y = 0; y < oldWallsizeY; y++) 
        {
            for (int z = 0; z < oldWallsizeZ; z++) {
                newWall = wallSegments[x,y,z];
                GameObject _wallSegment = newWall.gameObject;
                WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement> ();

                //same code but without giving the list indizes[] to the script/gameObject
                _WallMovement.initializeMovement ();
            }
        }
    }
}
IEnumerator waitForMovement()
{
    (...)
}
IEnumerator waitForMoving()
{
    yield return new WaitForSeconds(1f);
    wallMoving();
}

}

当我分开这行时 _WallMovement.initializeMovement (); 到另一个功能,游戏继续进行,但是这次墙没有动.印度人似乎不再被初始化.但是,这不会在控制台中导致错误.

When I separate this line _WallMovement.initializeMovement (); to another function, the game continues to work, but the wall doesnt move this time. The Indizes seem to not be initialized anymore. This however does not result in an error in the console.

这是WallMovement脚本中发生的事情,该脚本已附着到墙的每个立方体上:

This is what happens in the WallMovement script, that got attached to every cube of the wall:

public class WallMovement : MonoBehaviour {
public int[] indizes ;
int indize;

int modulo;

public void initializeMovement()
{
    modulo = indizes [0] % 2; 
    if (modulo>0) 
    {           
        //do something
    } 
    else 
    {
        // do something else
    }
}

}

推荐答案

我的错误是,我通过引用而不是按值将索引传递给脚本.

My mistake is, that I pass the indize by reference and not by value to the wallscripts.

因此,当我在主脚本中更改索引时,它们在每个墙脚本中都会更改. 因此,当我稍后调用隔离墙的公共功能时,它们都使用相同的indize,即我初始化的最后一个,因此首先不会受到我的"Initialization"的影响.

Therefore when I change the indizes in the main script they get changed in every wall script. So when I call the public functions of the wall later, they all use the same indizes, the last ones I initialized, and therefore are not effected by my "Initialization" in the first place.

否则,如果我在调用wall函数之前更改了indize值,则该值将再次起作用,因为脚本现在使用了正确的对应值,因此要更正我需要按值逐一传递indize,以使它们全部用相应的值初始化为实数.

Otherwise if I change the indizes values before I call the wall function it works again, because the script now uses the correct corresponding values, so to correct that I need to pass the indizes one by one by value so that they are all initialized for real with their corresponding value.

感谢您访问 https://catlikecoding.com/unity/tutorials/ 看着这个愚蠢的错误,告诉我这里没有其他人能做的事情.至少他没有尝试纠正我的代码速度慢.

Thanks go out to https://catlikecoding.com/unity/tutorials/ for looking over this really stupid mistake and tellig me what no one else here could. At least he didnt try to correct my code for being slow.

所以这是我的新代码段,但是效率低下,但仍然可以实现我想要的功能: 为了提高可读性,我没有编写所有可以再次使用的代码.它标有(...),并且保持不变

public class WallCreation : MonoBehaviour {

    (...) //stays the same as in the working code

    void Start () { 
        indizes= new int[3];
    }

    public void newWallScript(){
        initializeNewWall ("zWall++");
        StartCoroutine (waitForMovement ());
        StartCoroutine (waitForMoving()); //the new coroutine with a later start is added
    }

    void initializeNewWall(string replaceWall)
    {
        (...) //stays the same
    }

    void newWallMovement()
    {
        for (int x = 1; x < oldWallsizeX-1; x++)
        {
            indizes [0] = x;                   
            for (int y = 0; y < oldWallsizeY; y++) 
            {
                indizes [1] = y;
                for (int z = 0; z < oldWallsizeZ; z++) {
                    indizes[2] = z;

                    newWall = wallSegments[x,y,z];
                    GameObject _wallSegment = newWall.gameObject;
                    WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement> ();

                    //_WallMovement.indizes = indizes; //this is a 'passing by reference', because it is an array

                    _WallMovement.indizes[0] = indizes[0]; //these pass the parameter by value, you could also just say _WallMovement.indizes[0] = x; etc.
                    _WallMovement.indizes[1] = indizes[1];
                    _WallMovement.indizes[2] = indizes[2];

                    //this is cut out and put into the wallMoving() void
                    //_WallMovement.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];
                    GameObject _wallSegment = newWall.gameObject;
                    WallMovement _WallMovement = _wallSegment.GetComponent<WallMovement> ();

                    _WallMovement.initializeMovement ();
                }
            }
        }
    }
    IEnumerator waitForMovement()
    {
        (...) //stays the same
    }
    IEnumerator waitForMoving()
    {
        //the time to wait has no consequence on performance whatsoever
        yield return new WaitForSeconds(1f);
        wallMoving();
    }
}

这是我脚本中的一些其他代码:

这是现在在WallMovement脚本中发生的事情,该脚本已附着到墙的每个立方体上:

Here is some additional code from my script:

This is what happens in the WallMovement script now, that got attached to every cube of the wall:

public class WallMovement : MonoBehaviour {
    public int[] indizes ;
    int indize;

    int modulo;
void Awake (){
        indizes = new int[3]; // this is added, because we dont pass the list, but the single values, so it needs to be declared as a 3-dimensional array inbefore
    }

    public void initializeMovement()
    {
        modulo = indizes [0] % 2; 
        if (modulo>0) 
        {           
            //do something
        } 
        else 
        {
            // do something else
        }
    }
}

这篇关于Unity-重构的崩溃墙脚本停止工作了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆