0
\$\begingroup\$

In my game, you can spawn a cube by clicking. After 10 seconds I want the cube to disappear. That's what I'm trying to do in my code but it won't work:

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

public class circleThing : MonoBehaviour
{
    public GameObject circle;
    public GameObject block;
    public float time;
    void Start() {
         Vector3 temp = Camera.main.ScreenToWorldPoint(Input.mousePosition);
         temp.z = 5f;
         transform.position = temp;
         if (Input.GetMouseButtonDown(0)) {
             StartCoroutine(timer());
             Instantiate(block, temp, Quaternion.identity);
         }
         if (time >= 10) {
             Destroy(block);
         }
    }
    void Update()
    {
      
    }
     IEnumerator timer(){

        while (true)
        {
            Debug.Log(time);
            yield return new WaitForSeconds(1);
            time++;
        }
    }
}

What am I doing wrong? I get the error: Destroying assets is not permitted to avoid data loss.

\$\endgroup\$
0

2 Answers 2

0
\$\begingroup\$

In essence, you are not using Instantiate correctly. You pass in a GameObject (and other data) and it returns a copy.

In your code, you are not instantiating an object and setting it to block, you are instantiating a copy of block (which is nothing at this point I assume since you are not assigning anything to it in your code snippet) and not storing the returned GameObject in anything:

Instantiate(block, temp, Quaternion.identity);

What you need to do is create a variable that stores a Prefab cube that you then Instantiate and assign to block:

public GameObject circle;
    public GameObject CubePrefab; // use the Inspector to assign a cube prefab here
    public GameObject block;
    public float time;
    void Start()
    {
         Vector3 temp = Camera.main.ScreenToWorldPoint(Input.mousePosition);
         temp.z = 5f;
         transform.position = temp;
         if (Input.GetMouseButtonDown(0))
         {
             StartCoroutine(timer());
             block = Instantiate(CubePrefab, temp, Quaternion.identity);
         }
         [...]

or you can create a primitive Cube and manipulate its position/rotation:

[...]
if (Input.GetMouseButtonDown(0))
{
    StartCoroutine(timer());
    block = GameObject.CreatePrimitive(PrimitiveType.Cube);
    block.transform.position = temp;
    block.transform.rotation = Quaternion.identity;
}
[...]

As for your destroy method, unless you are trying to learn Coroutines, I would suggest you just use the built-in delay parameter in the signature for the Destroy method (as you already determined), which you would do immediately after creating the object:

block = Instantiate(CubePrefab, temp, Quaternion.identity);
Destroy(block, 10);

or alternatively you can do something like this:

public float blockCreateTime;
[...]
void Update()
{
    [...]
    block = Instantiate(CubePrefab, temp, Quaternion.identity);
    blockCreateTime = Time.time;
    [...]
    if (blockCreateTime - Time.time > 10)
    {
        Destroy(block);
    }
    [...]
}

I don't like that way of doing it, just letting you know that you can track time without creating a "timer" Coroutine.

As a little disclaimer, I haven't tried doing any of the above, that's just how Instantiate and GameObject.CreatePrimitive work. Also, in case you didn't know, Time.time will return how long the game has been running, so the check above subtracts the current duration the game has been running from the duration stored when you created the block to see if it is greater than the threshold (in this case 10s).

\$\endgroup\$
4
  • 1
    \$\begingroup\$ I found that out, but thanks for you're answer \$\endgroup\$
    – c0d3r
    Apr 16, 2021 at 17:07
  • \$\begingroup\$ @c0d3r yeah, I realized that after I posted the answer, but I figured I'd leave it up for informational purposes for anyone else looking to do something similar since your answer didn't explain the core issue, and mine has some alternatives. \$\endgroup\$
    – Daevin
    Apr 16, 2021 at 17:22
  • 1
    \$\begingroup\$ I decided to look back at this answer and I realized you put a better way to use a timer. Thanks for that, because couritene wasn't working too well. \$\endgroup\$
    – c0d3r
    Apr 27, 2021 at 17:32
  • \$\begingroup\$ @c0d3r no problem, happy to help! As awesome as Coroutines are, I often find that while I'm eager to use them, I need to stop and rethink if there's a simpler way to do them. \$\endgroup\$
    – Daevin
    Apr 27, 2021 at 18:49
0
\$\begingroup\$

So what I did is just this:

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

public class circleThing : MonoBehaviour
{
    public GameObject circle;
    public GameObject block;
    public float time;
    GameObject newBlock;
    void Start() {
         
    }
    void Update()
    {
      Vector3 temp = Camera.main.ScreenToWorldPoint(Input.mousePosition);
         temp.z = 5f;
         transform.position = temp;
         if (Input.GetMouseButtonDown(0)) {
             newBlock = Instantiate(block, temp, Quaternion.identity);
         }
             Destroy(newBlock, 10);
    }
}
```
\$\endgroup\$
2
  • \$\begingroup\$ You can move the Destroy inside the if so you don't call Destroy when there's nothing to be destroyed. You can also remove the empty Start function, make newBlock a local variable, and name your class with an initial uppercase letter to match the standard nomenclature. \$\endgroup\$
    – DMGregory
    Apr 15, 2021 at 21:35
  • \$\begingroup\$ The reason your earlier code wasn't working was you put it all in Start, which only runs once, the frame the object first spawns. So it won't be running a frame later when you click, or 10 seconds later when you want to destroy the block. By moving this code to Update, which runs every frame, you make sure you can detect a click no matter when it happens. \$\endgroup\$
    – DMGregory
    Apr 15, 2021 at 21:50

You must log in to answer this question.

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