Home > Back-end >  #Unity3D - Attach an object to another using a face of the last object as a target and deleting the
#Unity3D - Attach an object to another using a face of the last object as a target and deleting the

Time:12-13

Let's say that I have three simple box-like objects and I want to make different compositions by adding to the first object, already present in the scene, another one and then the other in whatever order i want by pressing a specific key on the keyboard (let's say W key for the Object 2 and S key for the Object 3).
For example:
enter image description here
After that I would like to delete the last present object every time I want by pressing Q key.
For example, I press W,W,S,W,S (Obj2, Obj2, Obj3, Obj2, Obj3).
After, I press Q three times (obtaining the composition Obj2, Obj2 because i destroyed the last three with Q).
And after that I press W one time (obtaining Obj2, Obj2, Obj2).

The modular part is made by a script put in an Empty GameObject(which is inside the Objects 1, 2 and 3.

public class Placement : MonoBehaviour
{
    public GameObject shape1, shape2, shape3;
    public Counter count;

    void Start()
    {
        count = FindObjectOfType<Counter>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            count.Array[count.i] = Instantiate(shape3, transform.position, transform.rotation);
            this.enabled = false;
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            count.Array[count.i] = Instantiate(shape2, transform.position, transform.rotation);
            this.enabled = false;
        }
        if (Input.GetKeyDown(KeyCode.Alpha6))
        {
                
        Destroy(count.Array[count.i]);
        count.i = count.i - 1;          
    }
}

Then I used a counter and a GameObject array to "save" each clone put in the scene in another generic script always present in the scene.

public class Counter : MonoBehaviour
{
    public int i = 0;
    public GameObject[] Array = new GameObject[50];

    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            i = i   1;
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            i = i   1;
        }
    }
}

The problems are:

  1. The first script is "reloaded" each time because it's inside every instantiated object I put in the scene, so I have to use an external single script where I save every counter and/or GameObject reference I need;
  2. If I remove this.enabled = false; from every Instantiate process the script partially works but it creates too many clones of the same object(because it's using every Empty GameObject in the scene as reference to where to put the clones and not just the last one present);
  3. By creating too many clones(even if I press W/S one single time), if I try to destroy the last one, it will destroy many others and if I try to put others after the destroying process, it will clone the object in every position available and not the last one.

I'm starting to lose my mind in a dumb process.... :')

CodePudding user response:

  1. Use one empty game object as ObjectSpawnManager to manage your object spawn/despawn behaviour, put the first script to this object, so that you don't need put the same script on multiple instances.

  2. Remove the Update part of Counter script, add public UpdateCounter method, and call it from ObjectSpawnManager script when the corresponding key down.

CodePudding user response:

Since you have stated a few problems and no specific questions, I am going to propose to you an approach that should work and implement what you ask for. If you want clarification on a specific question, feel free to ask.

As you have stated yourself, it makes more sense to have a single script manage the whole process of placing objects. Attach this script, let's call it SpawnManagerScript to an empty GameObject e.g. SpawnManager in the scene.

I would also suggest you to use a List instead of an array if you are not sure how many objects will be there at some point in time. If you do want to limit the number of objects to 50 (looking at your code), an array is totally fine.

Assuming you were able to figure out the correct positioning of the objects upon spawning already, I won't go into detail regarding that.

If I understood you correctly, what's left to do now is the following:

  1. Spawning GameObject: Differentiate the user input (e.g. S & W) in your SpawnManagerScript. For each type of object you could have a public field in your SpawnManagerScript class which references e.g. a Prefab or template GameObject in the scene. You can use the template object for cloning on user input. Add this clone to the List or array of objects and position it correctly.

  2. Deleting GameObject: Again, detect your desired input key for deletion in the script. Grab the last element in the List or the last added element in the array from the respective container. Destroy it or set it to inactive. Remove the entry from the container.

  • Related