HCI (UI User Interface / UX User eXperience)

Spawn and Despawn Objects when you Mouse Click in a Scene

You don’t have access to this lesson
Please register or sign in to access the course content.

There is an example of this here.

Setup a scene with varied terrain on it.

Create prefabs that can be used to spawn objects. You only need[3] one for this example.

Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if we have clicked on an object that we should be able to destroy / despawn.

In the main scene create a UIManager GameObject.

On this add the Player Input component[1].

Create input actions for this.

Add in a primary and secondary action for the left and right mouse button. These will be used to spawn and despawn items.

We are going to use a C# script for the input actions.

Select the Input Actions and then check Generare C# Class and then apply.

Create a C# class and attached to a UI Manager GameObject you create. In this example the C# scripts is called PrimaryClickItemSpawner

Points 1-6 setup the variables[2] and import the Input System[4] package.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 1. Import InputSystem
using UnityEngine.InputSystem;

public class PrimaryClickItemSpawner : MonoBehaviour
{
    // 2. Add Input actions (requires Generate C# script checked)
    private MouseControlsPointAndClick _controls;
    // 3. list of prefabs to be able to spawn (placeholder for later task)
    public GameObject[] prefabs = new GameObject[4]; //Prefabs to spawn
    // 4. List to store spawned gameobjects to be able to manage them.
    public List<GameObject> spawnedItems = new List<GameObject>();

    // 5. Currently selected prefab from list. Only default in this example
    int selectedPrefab = 0;
    // 6. Size of the raycast to draw.
    int rayDistance = 300;
}

Save the file and return to Unity. Drag the prefabs onto the prefabs array[5].

The code below is applied to a UI Manager GameObject and utilises a set of Input Actions that have a C# class generated for it.

Work through points 7-27 as detailed in the code comments below.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 1. Import InputSystem
using UnityEngine.InputSystem;

public class PrimaryClickItemSpawner : MonoBehaviour
{
    // 2. Add Input actions (requires Generate C# script checked)
    private MouseControlsPointAndClick _controls;
    // 3. list of prefabs to be able to spawn (placeholder for later task)
    public GameObject[] prefabs = new GameObject[4]; //Prefabs to spawn
    // 4. List to store spawned gameobjects to be able to manage them.
    public List<GameObject> spawnedItems = new List<GameObject>();

    // 5. Currently selected prefab from list. Only default in this example
    int selectedPrefab = 0;
    // 6. Size of the raycast to draw.
    int rayDistance = 300;

    // Start is called before the first frame update
    void Start()
    {
        // 7. Create new input actions using the C# script
        _controls = new MouseControlsPointAndClick();
        // 8. Enable / turn on the MouseRTS action map
        _controls.MouseRTS.Enable();
        // 9. When the PrimaryAction binding is performed call the PrimaryPerformed function
        _controls.MouseRTS.PrimaryAction.performed += PrimaryPerformed;
        /* 10. 
        When the PrimaryAction binding is released call the PrimaryCancelled function
        Not used in this example
        */
        _controls.MouseRTS.PrimaryAction.performed += PrimaryCancelled;
        // 11. Right mouse button pressed
        _controls.MouseRTS.SecondaryAction.performed += SecondaryPerformed;
        // 12. Right mouse button cancelled / released (not used)
        _controls.MouseRTS.SecondaryAction.canceled += SecondaryCancelled;
    }

    /* 13. 
    Primary button pressed. When left mouse pressed do this.
    Get the context of the button (what happened)
    This will cast a ray from the mouse position and see what it hits.
    */
    void PrimaryPerformed(InputAction.CallbackContext context) {
        // 15. Store the raycast hit result
        RaycastHit hit;
        // 16. Create a ray from the current mouse position through the screen towards the scene
        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        /* 17. 
        Cast the ray using the physics engine and see what it hits.
        Store what it (output) hits in the hit variable created earlier
        */
        if (Physics.Raycast(ray, out hit))
        {
            // 18. We are here because the raycast hit something

            /* 19.
            This is a messy check for the if statement.
            There are two main checks carried out.
            First we need to see if the parent of the hit object does not exist (e.g. hit null)
            Or check that the object it hit was not one of the objects tagged with
            player that we have spawned (otherwise we can spawn objects on top of each other)
            */
            if(hit.collider.transform.parent == null || hit.collider.transform.parent.CompareTag("Player") == false) {
                /* 20. 
                If we pass this instantiate (create) the object at the point the we hit
                the terrain (or other object)
                We use Quarternion.identiy to spawn it at the world space.
                */
                GameObject go = Instantiate(prefabs[selectedPrefab], hit.point, Quaternion.identity);
                // 21. Update the name of the prefab instance
                go.name += " _instantiated";
                // 22. Add it to the spawned items list.
                spawnedItems.Add(go);
            }
        } 
    }

    // 14. Primary button released not used in this example.
    void PrimaryCancelled(InputAction.CallbackContext context) {
                
    }

    /* 23.
    Now we want to despawn the item when we right click on it
    */
    void SecondaryPerformed(InputAction.CallbackContext context) {
        // 23. We run the same kind of checks as before but this runs when we right click
        RaycastHit hit;
        Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.ReadValue());
        if (Physics.Raycast(ray, out hit))
        {
            /* 24.
            Check if we hit the parent gameobject with the tag Player.
            */
            if(hit.collider.transform.parent.CompareTag("Player")) {
                // 25. If so remove the gameobject from the spawnedItems list
                spawnedItems.Remove(hit.transform.parent.gameObject);
                // 26. Then destroy the object to free up memory and remove it from the scene.
                Destroy(hit.transform.parent.gameObject);
            }
        }   
    }

    // 27. Not used in this example
    void SecondaryCancelled(InputAction.CallbackContext context) {
                
    }
}
Terms definitions
2. variables. “Containers” used to label and store data[8] in memory. The data can then be used throughout a program: * Integer[9] variables use only numbers and so can be used for calculations * String[10] variables are sequences of code that may contain numbers, letters, and other characters, and so cannot be used for calculations.
3. need. An identified requirement of a person, group, or environment[7]. A need is identified from an issue[11] and sits within a context[12]. Technological practice[6] can be undertaken in an attempt to meet an identified need.
4. System. A set of interconnected parts designed to transform, store, transport or control[13] materials, energy and/or information.
5. array. A data structure that is a collection of elements, each element has what is called an array index or key, which can be thought of as a pointer. And you can refer to that element by calling it’s index or key.
Terms definitions
1. component. There is an example of this here. Setup a scene with varied terrain on it. Create prefabs that can be used to spawn objects. You only need one for this example. Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if […]
2. variables. There is an example of this here. Setup a scene with varied terrain on it. Create prefabs that can be used to spawn objects. You only need one for this example. Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if […]
3. need. There is an example of this here. Setup a scene with varied terrain on it. Create prefabs that can be used to spawn objects. You only need one for this example. Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if […]
4. System. There is an example of this here. Setup a scene with varied terrain on it. Create prefabs that can be used to spawn objects. You only need one for this example. Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if […]
5. array. There is an example of this here. Setup a scene with varied terrain on it. Create prefabs that can be used to spawn objects. You only need one for this example. Set the parent of the prefab to have a tag named Player (or whatever you wish). We will use this later to check if […]