Unity - Refactored crumbling wall script stops working?

前端 未结 2 1232
囚心锁ツ
囚心锁ツ 2021-01-16 00:44

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, bu

相关标签:
2条回答
  • 2021-01-16 01:05

    First of all do not mess with anything you don't have to until you actually get your refactored code working. Otherwise you will be trying to fix multiple problems.

    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;
                    }
                }
            }
        } 
    

    Leave everything the same and only remove _WallMovement.initializeMovement ();.

    Now you will have to call the same function, somewhere else. This is incredibly inefficient because you now have to iterate through every wall position AGAIN, instead of doing everything at once.

    Here is an example.

    Private List<WallMovement> WallCollection = new List<WallMovement>();
    private WallMovement 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;
                        WallCollection.Add(_WallMovement);
                    }
                }
            }
        } 
    

    When you call these two functions you can do something like this

    IEnumerator waitForMovement()
    {
       newWallMovement();
       yield return new WaitForSeconds(1f);
       InializeAllWallMovement();
    }
    
    private void InializeAllWallMovement()
    {
       foreach(WallMovement wm in WallCollection)
       {
          wm.initializeMovement(); 
       }
    }
    

    As you can see this is not actually an improvement, but makes your code more complicated and take longer. The way it was before was probably about as simplified as this is going to get. If you must move that code outside because it is necessary for some reason, then try something like what I suggested.

    0 讨论(0)
  • 2021-01-16 01:10

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

    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.

    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.

    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.

    So this is my new code segment that works, but is inefficient, still it does exactly what I wanted: For better readability I dont write all the code that worked again. It is marked with (...) and stays the same

    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();
        }
    }
    

    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
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题