0
\$\begingroup\$

Instead of using a list, I want to use a two-dimensional array of objects and a two-dimensional array of transforms.

But instantiations do not work with this code in C sharp:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class try_array_instantiate : MonoBehaviour {

  //entity declaration
  public GameObject[,] cube;
  public GameObject cube_initial;
  public GameObject[,] cubeCree;
  public Transform[,] origine;
  public Transform origine_initial;
  public float moveSpeed=5f;

  int i;

 void Start() {  
    // take the transformation composantres of the initial cube
    origine_initial=cube_initial.GetComponent<Transform>();
  }

  void Update() {

    if (Input.GetKeyDown (KeyCode.Q)) {
      //create the first shot duplication from the single initial cube
      cube[1,1]=Instantiate (cubeCree[1,1], origine_initial.position, origine_initial.rotation) as GameObject;
      cube[1,1].transform.Translate(Time.deltaTime*moveSpeed,0,Time.deltaTime*moveSpeed,Space.Self);

      cube[1,2]=Instantiate (cubeCree[1,1], origine_initial.position, origine_initial.rotation) as GameObject;
      cube[1,2].transform.Translate(Time.deltaTime*moveSpeed,0,-Time.deltaTime*moveSpeed,Space.Self);
      //destruction of the initial cube
      Destroy(cube_initial);
    }
  }
}

What should I modify in this code so that the instantations are created?

In fact, I can't adapt your correction at this code I would like to do initially which makes a duplicate shot with each press of the Q key.

Here's this code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tir_duplique_pas_encore_bon : MonoBehaviour {

    // If what we want to work with are Transforms, then store that reference directly.
    public Transform[,] cubeInitial;
    public Transform[,] cubePrefab;
    public Transform cubePrefab0;
    public Transform cubeInitial0;

    public float moveSpeed = 5f;
    int i;
    int p=0;

    // Private variables for the content we populate at runtime.
    Transform[,] cubes;
    Vector3 originPosition;
    Quaternion originRotation;        

    void Start() {
        // Initialize the array before we try to use it.
        // Note that arrays are 0-based, so if we later want to access [1, 2],
        // that means we need at least a 2x3 array (ie. {0, 1} x {0, 1, 2})
        cubes = new Transform[100000,1];
        cubeInitial = new Transform[100000,1];
        cubePrefab = new Transform[100000,1];
        cubePrefab0 = cubePrefab [0, 0];
        cubeInitial0 = cubeInitial [0, 0];

    }

    void Update() {
        if (Input.GetKeyDown (KeyCode.Q)) {

            // Capture the transformation of our reference object before we delete it.
            if(cubeInitial[0,0] != null) {
                originPosition = cubeInitial[0,0].position;
                originRotation = cubeInitial[0,0].rotation;
                //Destroy(cubeInitial[0,0]);
                //cubeInitial[0,0] = null;
            }

            // Instantiate our cube instances using the prefab.
            cubes[0, 0] = Instantiate<Transform>(cubePrefab[0,0], originPosition, originRotation);
            cubes[0, 1] = Instantiate<Transform>(cubePrefab[0,1], originPosition, originRotation);


        // If you want these objects to move over time, then don't
        // put the Translate() call inside a block that runs only
        // when the player presses "Q". Move them every frame.

        float step = Time.deltaTime * moveSpeed;

        if(cubes[0,0] != null)
            cubes[0,0].Translate(step, 0, step, Space.Self);

        if(cubes[0,1] != null)
            cubes[0,1].Translate(step, 0, -step, Space.Self);

    }
        if (Input.GetKeyDown (KeyCode.Q)) {

            for (i=(int)Mathf.Pow (2, p+1)-1; i <=2*((int)Mathf.Pow (2, p+1)-1) ;i++ )
            {if(cubeInitial[i-1,0] != null) {
                    originPosition = cubeInitial[i-1,0].position;
                    originRotation = cubeInitial[i-1,0].rotation;
                    Destroy(cubeInitial[i-1,0]);
                    cubeInitial[i-1,0] = null;
                }

            if(cubeInitial[i-1,1] != null) {
                    originPosition = cubeInitial[i-1,1].position;
                    originRotation = cubeInitial[i-1,1].rotation;
                    Destroy(cubeInitial[i-1,1]);
                    cubeInitial[i-1,1] = null;
                }

                cubes[i, 0] = Instantiate<Transform>(cubePrefab[i,0], originPosition, originRotation);
                cubes[i, 1] = Instantiate<Transform>(cubePrefab[i,1], originPosition, originRotation);

                float step = Time.deltaTime * moveSpeed;

                if(cubes[i,0] != null)
                        cubes[0,0].Translate(step, 0, step, Space.Self);

                if(cubes[i,1] != null)
                        cubes[i,1].Translate(step, 0, -step, Space.Self);

}
                        p++;
}
}
}

I try to apply your answer to my update code and I have problem here:

Instead of declaring transform cubePrefab and cubeInitial, I declare:

public transform[,] cubeInitial;
public transform[,] cubePrefab;

To adapt the following of my new code updated which must uses arrays to classify shoot which are multiplying

So,no possible to slip in the inspector in the script the firstcube(shoot) like I did it with your first code thanks to:

public Transform cubeInitial;
public Transform cubePrefab;

After,i tried to to that:

public Transform[,] cubeInitial;
public Transform[,] cubePrefab;
public Transform cubePrefab0;
public Transform cubeInitial0;

and after:

cubes = new Transform[100000,1];
cubeInitial = new Transform[100000,1];
cubePrefab = new Transform[100000,1];
cubePrefab0 = cubePrefab [0, 0];
cubeInitial0 = cubeInitial [0, 0];

So, compile was good but shoot doesn't work on play unity

Then,to adapt your update,i write this last code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class tir_duplique_pas_encore_bon : MonoBehaviour {
    // If what we want to work with are Transforms, then store that reference directly.
    public Transform[,] cubeInitial;
    public Transform[,] cubePrefab;
    public Transform cubePrefab0;
    public Transform cubeInitial0;
    public float moveSpeed = 5f;
    int i;
    int p=1;
    // Private variables for the content we populate at runtime.
    Transform[,] cubes;
    Vector3 originPosition;
    Quaternion originRotation;

    void Start() {
        // Initialize the array before we try to use it.
        // Note that arrays are 0-based, so if we later want to access [1, 2],
        // that means we need at least a 2x3 array (ie. {0, 1} x {0, 1, 2})
        cubes = new Transform[100000,1];
        cubeInitial = new Transform[100000,1];
        cubePrefab = new Transform[100000,1];
        cubePrefab0 = cubePrefab [0, 0];
        cubeInitial0 = cubeInitial [0, 0];

    }

    void Update() {
        if (Input.GetKeyDown (KeyCode.Q)) {

            // Capture the transformation of our reference object before we delete it.
            if(cubeInitial[0,0] != null) {
                originPosition = cubeInitial[0,0].position;
                originRotation = cubeInitial[0,0].rotation;
                Destroy(cubeInitial[0,0]);
                cubeInitial[0,0] = null;
            }

            // Instantiate our cube instances using the prefab.
            cubes[0, 0] = Instantiate<Transform>(cubePrefab[0,0], originPosition, originRotation);
            cubes[0, 1] = Instantiate<Transform>(cubePrefab[0,0], originPosition, originRotation);


            // If you want these objects to move over time, then don't
            // put the Translate() call inside a block that runs only
            // when the player presses "Q". Move them every frame.

            float step = Time.deltaTime * moveSpeed;

            if(cubes[0,0] != null)
                cubes[0,0].Translate(step, 0, step, Space.Self);

            if(cubes[0,1] != null)
                cubes[0,1].Translate(step, 0, -step, Space.Self);
        }
        if (Input.GetKeyDown (KeyCode.Q)) {
            for (i=(int)Mathf.Pow (2, p); i <= (int)Mathf.Pow (2, p + 1) - 1;i++ )
            {
                if(cubeInitial[i,0] != null) {
                    originPosition = cubeInitial[i,0].position;
                    originRotation = cubeInitial[i,0].rotation;
                    Destroy(cubeInitial[i,0]);
                    cubeInitial[i,0] = null;
                }

                if(cubeInitial[i,1] != null) {
                    originPosition = cubeInitial[i,1].position;
                    originRotation = cubeInitial[i,1].rotation;
                    Destroy(cubeInitial[i,1]);
                    cubeInitial[i,1] = null;
                }

                cubes[i, 0] = Instantiate<Transform>(cubePrefab[i,0], originPosition, originRotation);
                cubes[i, 1] = Instantiate<Transform>(cubePrefab[i,1], originPosition, originRotation);

                float step = Time.deltaTime * moveSpeed;

                if(cubes[i,0] != null)
                    cubes[0,0].Translate(step, 0, step, Space.Self);

                if(cubes[i,1] != null)
                    cubes[i,1].Translate(step, 0, -step, Space.Self);
            }
            p++;
        }
    }
}

But it doesn't work on play Unity

Yes sorry the console of Unity indicate:

ArgumentException: The Object you want to instantiate is null. UnityEngine.Object.CheckNullArgument (System.Object arg, System.String message) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:239) UnityEngine.Object.Instantiate (UnityEngine.Object original, Vector3 position, Quaternion rotation) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:151) UnityEngine.Object.Instantiate[Transform] (UnityEngine.Transform original, Vector3 position, Quaternion rotation) (at C:/buildslave/unity/build/Runtime/Export/UnityEngineObject.cs:206) tir_duplique_pas_encore_bon.Update () (at Assets/tir_duplique_pas_encore_bon.cs:54)

code source contains at the beginning:

cubePrefab0 = cubePrefab [0, 0]; cubeInitial0 = cubeInitial [0, 0];

so 2 fields appear in the script of the inspector. Then,in thes 2 fields,I slid another same cube in the hierarchy that has no script Is it no sufficient?

\$\endgroup\$
5
  • \$\begingroup\$ When you say they "do not work," can you elaborate? What are the exact symptoms of the problem? Do you get a runtime error of some kind? \$\endgroup\$
    – DMGregory
    Commented Apr 15, 2019 at 15:43
  • \$\begingroup\$ How did you try applying the answer below to your updated code? Where specifically did you run into trouble adapting it? \$\endgroup\$
    – DMGregory
    Commented Apr 16, 2019 at 1:14
  • \$\begingroup\$ Also format your code so we can read it. \$\endgroup\$ Commented Apr 16, 2019 at 3:31
  • \$\begingroup\$ "It doesn't work" is never enough information about the symptoms to diagnose the cause. Always describe in what specific way it does not work. Do you get a compiler error or runtime error? Do you get behaviour that differs from what you wanted? How does it differ? Does your computer crash or catch fire? This is important information to include in your question. \$\endgroup\$
    – DMGregory
    Commented Apr 16, 2019 at 10:08
  • \$\begingroup\$ "The object you want to instantiate is null" says that the object you passed to Instantiate() is empty. Where in your project do you assign a value to cubePrefab[0,0] before you try to spawn it? How do you expect the game engine to know what kind of object you want to spawn there? \$\endgroup\$
    – DMGregory
    Commented Apr 16, 2019 at 13:04

1 Answer 1

3
\$\begingroup\$

The main errors here are:

  1. Failing to create your array with cubeCree = new GameObject[2,3]; before trying to assign contents to it. Always ensure you've created the array with the appropriate dimensions before trying to use it, otherwise you'll get a null reference or out of bounds exception.

  2. Destroying the cube_initial object when your code is going to try to read from it again the next time the "Q" key is pressed. Be sure to save the properties from it that you'll need, and check for null before trying to access the destroyed object.

  3. Trying to use multidimensional arrays as public variables - the Unity Inspector won't let you initialize multidimensional arrays that way.

Corrected code might look something like this:

public class ArrayInstantiate : MonoBehaviour {

  // If what we want to work with are Transforms, then store that reference directly.
  public Transform cubeInitial;
  public Transform cubePrefab;

  public float moveSpeed = 5f;

  // Private variables for the content we populate at runtime.
  Transform[,] cubes;
  Vector3 originPosition;
  Quaternion originRotation;    
  

  void Start() {
      // Initialize the array before we try to use it.
      // Note that arrays are 0-based, so if we later want to access [1, 2],
      // that means we need at least a 2x3 array (ie. {0, 1} x {0, 1, 2})
      cubes = new Transform[2,3];
  }

  void Update() {
    if (Input.GetKeyDown (KeyCode.Q)) {

      // Capture the transformation of our reference object before we delete it.
      if(cubeInitial != null) {
        originPosition = cubeInitial.position;
        originRotation = cubeInitial.rotation;
        Destroy(cubeInitial);
        cubeInitial = null;
      }

      // Instantiate our cube instances using the prefab.
      cubes[1, 1] = Instantiate<Transform>(cubePrefab, originPosition, originRotation);
      cubes[1, 2] = Instantiate<Transform>(cubePrefab, originPosition, originRotation);
    }

    // If you want these objects to move over time, then don't
    // put the Translate() call inside a block that runs only
    // when the player presses "Q". Move them every frame.

    float step = Time.deltaTime * moveSpeed;

    if(cubes[1,1] != null)
        cubes[1,1].Translate(step, 0, step, Space.Self);
    
    if(cubes[1,2] != null)
        cubes[1,2].Translate(step, 0, -step, Space.Self);
  }
}

It's not clear to me why you've moving your cubes within the ArrayInstantiate class, nor why you're using only indices [1, 1] and [1, 2] out of your array, but I've left these as-is in this version of the code. I'd recommend sizing the array to contain only the indices you need, and putting the cube movement in a separate script on the cubes themselves, so you don't need to manage their ongoing behaviour from the script that spawns them.


Based on the edit, you seem to be very confused about how arrays in C# work. For example, you initialize your arrays like this in Start:

cubeInitial = new Transform[100000,1];
cubeInitial0 = cubeInitial [0, 0];

but then try to access it like this:

cubeInitial[i,1].position

This is wrong for a few reasons:

  1. You told the compiler you wanted only one entry along the second dimension (new Transform[100000, 1]), so that means that while cubeInitial[i,0] is a valid index (for i < 100000), cubeInitial[i,1] is not. You're trying to use two entries for each i, but you allocated only one.

  2. You've created a new, empty array in Start, so every entry of cubeInitial[,] is null (an empty slot). It will not have a position or rotation until you assign a Transform instance to that index.

  3. It looks like you tried to initialize cubeInitial[0,0] with this line: cubeInitial0 = cubeInitial [0, 0]; but this assigns the value of cubeInitial[0,0] (which is null) into cubeInitial0, so now both variables hold the value of null, and this doesn't help you at all.

    Maybe you meant to assign the value of cubeInitial0 into cubeInitial[0,0] like so: cubeInitial[0,0] = cubeInitial0;, but that still leaves nulls in all entries of the form cubeInitial[i,1], provided you solve the array size issue mentioned in point 1.

Because of confusion like this, it's very difficult to understand how you expected this code to work, or what you want it to accomplish.

I'd recommend taking some time to brush up on your C# fundamentals: maybe take a break from your game development project and work through some beginner tutorials for the language.

The other thing you can do is to try phrasing your questions to ask about the feature you want to achieve, not the coding syntax you're using to try to achieve it. Since you don't yet understand the syntax, this is leading to garbled questions and X/Y Problems. Instead, walk us step by step through how this game feature should work, what happens when everything goes as planned. Include diagrams or animations, or examples from similar games, if they help you to communicate clearly.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .