Fixing CS0039

I have an error CS0039, and I’m not sure how to fix it.
It says, “cannot convert type ‘Rocks’ to ‘UnityEngine.GameObject’ via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion”.
I’m trying to respawn random sprites (Rocks) and have them move again after the first wave of sprites is destroyed. The line with the error is labeled below (RockSpawner.cs, line 71).

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
/// <summary>
/// A rock spawner
/// </summary>
public class RockSpawner : MonoBehaviour
{
    // needed for spawning
    [SerializeField]
    GameObject prefabRocks;
    // saved for efficiency
    [SerializeField]
    Sprite greenrock0;
    [SerializeField]
    Sprite magentarock1;
    [SerializeField]
    Sprite whiterock2;
    // spawn control
    const float MinSpawnDelay = 1;
    const float MaxSpawnDelay = 2;
    Timer spawnTimer;
    // spawn location support
    const int SpawnBorderSize = 100;
    int minSpawnX;
    int maxSpawnX;
    int minSpawnY;
    int maxSpawnY;
    /// <summary>
    /// Use this for initialization
    /// </summary>
    void Start()
    {
        // save spawn boundaries for efficiency
        minSpawnX = SpawnBorderSize;
        maxSpawnX = Screen.width - SpawnBorderSize;
        minSpawnY = SpawnBorderSize;
        maxSpawnY = Screen.height - SpawnBorderSize;
        // create and save timer
        spawnTimer = gameObject.AddComponent<Timer>();
        spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
        spawnTimer.Run();
    }
    /// <summary>
    /// Update is called once per frame
    /// </summary>
    void Update()
    {
        // check for time to spawn a new random rock
        if (spawnTimer.Finished)
        {
            SpawnRock();   // change spawn timer duration and restart
            spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
            spawnTimer.Run();
        }
 
    }
    /// <summary>
    /// spawns a new rock at a random location
    /// </summary>
 
    public void SpawnRock()
    {
        // generate random location and create a new rock
        Vector3 location = new Vector3(Random.Range(minSpawnX, maxSpawnX),
        Random.Range(minSpawnY, maxSpawnY),
        -Camera.main.transform.position.z);
        Vector3 worldLocation = Camera.main.ScreenToWorldPoint(location);
        GameObject Rock = Instantiate(new Rocks()) as GameObject; // error is here
        Rock.transform.position = worldLocation;
        // set random sprite for new rock
        SpriteRenderer spriteRenderer = prefabRocks.GetComponent<SpriteRenderer>();
        int SpriteNumber = Random.Range(0, 3);
        if (SpriteNumber == 0)
        {
            spriteRenderer.sprite = greenrock0;
        }
        else if (SpriteNumber == 1)
            spriteRenderer.sprite = magentarock1;
        else
        {
            spriteRenderer.sprite = whiterock2;
        }
        Rock.SetActive(true);
    }
 
 
}
<summary>
Rocks.cs
</summary>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.VFX;
public class Rocks : MonoBehaviour
{
    // death support
 
    //Timer deathTimer;
    void Start()
    {
        /// <summary>
        /// Use this for initialization
        /// </summary>
        // apply impulse force to get the object moving
        const float MinImpulseForce = 2f;
        const float MaxImpulseForce = 3f;
        float angle = Random.Range(0, 2 * Mathf.PI);
        Vector2 direction = new Vector2(
            Mathf.Cos(angle), Mathf.Sin(angle));
        float magnitude = Random.Range(MinImpulseForce, MaxImpulseForce);
        GetComponent<Rigidbody2D>().AddForce(
            direction * magnitude,
            ForceMode2D.Impulse);
        ///<summary>
        ///Use this for initialization
        ///</summary>
        // create and start timer
        //deathTimer = deathTimer = gameObject.AddComponent<Timer>();
        //deathTimer.Duration = greenrocklifeseconds;
        //deathTimer.Duration = magentarocklifeseconds;
        //deathTimer.Duration = whiterocklifeseconds;
        //deathTimer.Run();
    }
    // Update is called once per frame
    void Update()
    {
        //if (deathTimer != null && deathTimer.Finished)
        //{
        //    Destroy(gameObject);
        //}
    }
    ///<summary>
    ///Self-destruct when sprites leave scene
    ///</summary>
   void OnBecameInvisible()
    {
        //Destroy(gameObject);
   
 
        }
 
 }

You can’t use the new keyword on any MonoBehaviours.
Make the rock a prefab, put it in a class member at the beginning of your SpawnRock class just like the prefabRocks and then Instantiate that prefab. It will create separate game objects out of it.

Unless the prefabRocks is the very same thing. It’s hard to tell.

Forgot to add - in Unity I have a prefabRocks folder and I put in greenrocks0, magentarock1, and whiterock2. I attached both scripts to all three sprites in the prefab folder and the main camera.

I put “GameObject PrefabRocks” because that’s the name of the prefab folder in unity.

I removed “new” and put in “prefabRocks” and it gives me CS1955.

I’m new to C# so I have no idea how to put in a class member at the beginning of the spawnrock class

Did you put it like that?
Instantiate(prefabRocks())
It must be:
GameObject Rock = Instantiate(prefabRocks);
No need in “as GameObject”.

If I put in both then Instantiate(prefabRocks()) gives CS1955: “Non-invocable member ‘RockSpawner.prefabRocks’ cannot be used as a method.”

GameObject Rock = Instantiate(prefabRocks); alone gives no errors in Visual Studio but when I run unity then it says that all my sprites and “prefabRocks” is never assigned to, which makes its default value null.

https://docs.unity3d.com/Manual/InstantiatingPrefabs.html

This applies to 2D as well…?

Yes.

Here’s the snapshot from my unity:

Now it says in unity that the variable prefabRocks of Rockspawner has not been assigned. For the code I only added GameObject Rock = Instantiate(prefabRocks);

You really gotta push through this sorta stuff… it’s like forgetting to dot your i or cross your t… you will do it FOREVER into the future. It’s part of software engineering. I’ve been doing this for 41 years and I still forget to drag references in, literally over once an hour usually (!!!) when I’m working fast.

The good news is that you almost always can help yourself to find it quickly, and get onto real work not dotting is and crossing ts.

Some notes on how to fix a NullReferenceException in Unity3D (also Unassigned Reference errors):

http://plbm.com/?p=221

You can do it.

Instantiating/Destroying objects seems overkill for this task. Is this really needed?
You can just make Reset() method that will reset position/movement/sprite/whatever of the rock when it reaches screen edge/timer.
Also google “Object Pooling”. It’s more efficient technique for this.

Ok, now I managed to respawn sprites after the previous ones are destroyed. The new ones just don’t move.

Is there a way to move the cloned sprites at a random velocity?
Updated C#:

using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
/// <summary>
/// A rock spawner
/// </summary>
public class RockSpawner : MonoBehaviour
{
    // needed for spawning
    [SerializeField]
    GameObject prefabRocks;
    // saved for efficiency
    [SerializeField]
    Sprite greenrock0;
    [SerializeField]
    Sprite magentarock1;
    [SerializeField]
    Sprite whiterock2;
    // spawn control
    const float MinSpawnDelay = 1;
    const float MaxSpawnDelay = 2;
    Timer spawnTimer;
    // spawn location support
    const int SpawnBorderSize = 100;
    int minSpawnX;
    int maxSpawnX;
    int minSpawnY;
    int maxSpawnY;
    /// <summary>
    /// Use this for initialization
    /// </summary>
 void Start()
    {
      
    // save spawn boundaries for efficiency
    minSpawnX = SpawnBorderSize;
        maxSpawnX = Screen.width - SpawnBorderSize;
        minSpawnY = SpawnBorderSize;
        maxSpawnY = Screen.height - SpawnBorderSize;
        // create and save timer
        spawnTimer = gameObject.AddComponent<Timer>();
        spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
        spawnTimer.Run();
    }
    /// <summary>
    /// Update is called once per frame
    /// </summary>
    void Update()
    {
        // check for time to spawn a new random rock
        if (spawnTimer.Finished)
        {
            SpawnRock();
        }
        // change spawn timer duration and restart
        spawnTimer.Duration = Random.Range(MinSpawnDelay, MaxSpawnDelay);
        spawnTimer.Run();
    }
    /// <summary>
    /// spawns a new rock at a random location
    /// </summary>
    void SpawnRock()
    {
        // generate random location and create a new rock
        Vector3 location = new Vector3(Random.Range(minSpawnX, maxSpawnX),
            Random.Range(minSpawnY, maxSpawnY),
            -Camera.main.transform.position.z);
        Vector3 worldLocation = Camera.main.ScreenToWorldPoint(location);
      
        GameObject Rocks = Instantiate(prefabRocks);
        prefabRocks.transform.position = worldLocation;
      
        // set random sprite for new rock
        SpriteRenderer spriteRenderer = Rocks.GetComponent<SpriteRenderer>();
        int SpriteNumber = Random.Range(0, 3);
        if (SpriteNumber == 0)
        {
            spriteRenderer.sprite = greenrock0;
        }
      
        else if (SpriteNumber == 1)
                spriteRenderer.sprite = magentarock1;
        else
        {
            spriteRenderer.sprite = whiterock2;
        }
      
    }
    }
  
  
  
///<summary>
/// Spawns a new rock at a random location
///</summary>
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Rocks script
/// </summary>
public class Rocks : MonoBehaviour
{
  
    void Start()
    {
      
        /// <summary>
        /// Use this for initialization
        /// </summary>
        // apply impulse force to get the object moving
      
        const float MinImpulseForce = 2f;
        const float MaxImpulseForce = 3f;
        float angle = Random.Range(0, 2 * Mathf.PI);
        Vector2 direction = new Vector2(
            Mathf.Cos(angle), Mathf.Sin(angle));
        float magnitude = Random.Range(MinImpulseForce, MaxImpulseForce);
        GetComponent<Rigidbody2D>().AddForce(
            direction * magnitude,
            ForceMode2D.Impulse);
      
        ///<summary>
        ///Use this for initialization
        ///</summary>
      
    }
    // Update is called once per frame
    void Update()
    {
      
        
    
    }
    ///<summary>
    ///Self-destruct when sprites leave scene
    ///</summary>
  
    void OnBecameInvisible()
    {
        Destroy(gameObject);
        Instantiate(gameObject, new Vector3(), new Quaternion());
      
    }
  
}

I updated the code now:

 void SpawnRock()
    {
        Vector3 location = new Vector3(Random.Range(minSpawnX, maxSpawnX),
            Random.Range(minSpawnY, maxSpawnY),
            -Camera.main.transform.position.z);
        Vector3 worldLocation = Camera.main.ScreenToWorldPoint(location);
        //spawn random prefab
        int prefabNumber = Random.Range(0, 3);
        if (prefabNumber == 0)
        {
            Instantiate<GameObject>(prefabgreenrock, worldLocation, Quaternion.identity);
        }
        else if (prefabNumber == 1)
        {
            Instantiate<GameObject>(prefabmagentarock, worldLocation, Quaternion.identity);
        }
        else if (prefabNumber == 2)
        {
            Instantiate<GameObject>(prefabwhiterock, worldLocation, Quaternion.identity);
        }
    }
}

I’ve also tried putting

       const float MinImpulseForce = 2f;
        const float MaxImpulseForce = 3f;
        float angle = Random.Range(0, 2 * Mathf.PI);
        Vector2 direction = new Vector2(
            Mathf.Cos(angle), Mathf.Sin(angle));
        float magnitude = Random.Range(MinImpulseForce, MaxImpulseForce);
        GetComponent<Rigidbody2D>().AddForce(
            direction * magnitude,
            ForceMode2D.Impulse);

below each GameObject to move the newly spawned rocks at random velocity & direction but it made no difference. I removed the GameObject prefabRocks cause it was redundant since GameObject prefabgreenrock, prefabmagentarock, and prefabwhiterock already exist.