Can't recall a gameObject from List

Hello everyone,

I’m pretty new to Unity and I have a question which might be very fundamental. I’ve spent hours on this to solve but no way out. Here’s my problem.

Now, what I’m trying to do is that I have 2 scripts and 2 game objects.

  • 1st game object is my game board and its attached script change tile colors on it.
  • 2nd game object is a dice and its script generates a random number.

My objective is to let player choose tiles to be bet on, color it light green (I’ve done it) and if the dice is more than 7, turn the selected tiles to dark green. Below are my codes.

Change Tiles;

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

public class Win_Green : MonoBehaviour
{
public Sprite TileSprites;
public GameObject Dice_Button;
public List TileList;

void Update()
{
    
    if (Input.GetMouseButton(0))
    {            
        List<GameObject> TileList = new List<GameObject>();
        RaycastHit2D hit = Physics2D.Raycast(new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y), Vector2.zero);
        
        if (hit)
        {
            hit.transform.gameObject.GetComponent<SpriteRenderer>().sprite = TileSprites[0];
            TileList.Add(hit.transform.gameObject);
            Debug.Log(TileList[0]);               
        }
    }
}  

}

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

public class Roll_Dice : MonoBehaviour
{
public int Dice_Score;
public Text Dice_Text;
public Button Exit_Button;
public GameObject Board;
public GameObject TileListNew;
public Sprite TileSprites;

// Use this for initialization
void Start()
{
    Exit_Button.gameObject.SetActive(false);
    Dice_Text.text = " ";
    Button btn1 = GetComponent<Button>();
    btn1.onClick.AddListener(TaskOnClick);
}

void TaskOnClick()
{
    gameObject.SetActive(false);
    Dice_Score = Random.Range(2, 13);
    Dice_Text.gameObject.SetActive(true);
    Dice_Text.text = "Rolled" + " " + Dice_Score;
    GameObject TileListNew = new GameObject();
    Board.gameObject.GetComponent<Win_Green>().enabled = false;
    TileListNew = Board.gameObject.GetComponent<Win_Green>().TileList[0];          
    Invoke("Close_Dice_Roll", 3);
   
    
}

void Close_Dice_Roll()
{
    Dice_Text.gameObject.SetActive(false);
    gameObject.SetActive(true);
    int Score = gameObject.GetComponent<Roll_Dice>().Dice_Score;
    Board.gameObject.GetComponent<Win_Green>().enabled = true;
   
    if (Score > 1)
    {
       Paint_Tiles(TileListNew);
    }

   
}

void Paint_Tiles(GameObject TileListInstance)
{               
    TileListInstance.gameObject.GetComponent<SpriteRenderer>().sprite = TileSprites[1];
}

}

Here is an example on how you can click on gameobjects with a spriteRenderer and save it for modifications later. I left out the part with generating the random number to keep it simple. Now first I must say you can skip the part in the Start method and just add the spriteRenderer in the editor yourself. This really depends on how many you have. But this way can you find and the tiles just by adding a reference to their parent gameobject.


Add this script to an empty gameobject called BoardManager

public class BoardManager : MonoBehaviour {

	public Transform tileParent;	

	public Sprite[] tilecolors; 

	private SpriteRenderer[] tiles;
	private List<SpriteRenderer> selectedTiles;
	private float closeDiceDelay = 3;
	private bool diceIsClosing;

	void Start () {
		selectedTiles = new List<SpriteRenderer>();

		// # IMPORTANT ~ You have to ensure that all gameobjects you drop inside the gameobject 'tileParent', have a SpriteRenderer component or will get an error below.
		// Set the length of our array to the count of gameobjects in the first hierachy inside 'tileParent'
		tiles = new SpriteRenderer[tileParent.childCount];
		
		// Cache all our tiles for later use.
		for (int i = 0; i < tileParent.childCount; i++) {

			var spriteRender = tileParent.GetChild(i).GetComponent<SpriteRenderer>();
			tiles *= spriteRender;*
  •  }*
    
  • }*

  • void Update () {*

  •  // We want to check if the dice is not closing, so our players don't add some new tiles which automatically will be removed by the CloseDiceDelay*
    
  •  if (Input.GetMouseButton(0) && !diceIsClosing) {*
    
  •  	RaycastHit2D hit = Physics2D.Raycast(new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y), Vector2.zero);			*
    
  •  	// We only want to select gameobjects we added the tag 'Tiles' to.*
    

// More information about tags here Unity - Manual: Tags

  •  	if (hit && hit.collider.CompareTag("Tile")) {*
    
  •  		SelectTileFrom(hit.collider);*
    
  •  	}*
    
  •  }*
    
  • }*

  • void SelectTileFrom(Collider2D collider) {*

  •  var spriteRender = collider.GetComponent<SpriteRenderer>();*
    
  •  if (spriteRender == null) {*
    
  •  	Debug.Log("You clicked on a gameObject with the Tile tag without a spriteRender");*
    
  •  	return; // stop our method from running the rest of the code IN THIS method*
    
  •  }*
    
  •  // change the sprite*
    
  •  spriteRender.sprite = tilecolors[0];*
    
  •  // save our selected spriteRender for later use.*
    
  •  selectedTiles.Add(spriteRender);*
    
  • }*

  • void DoSomethingWithSelectedTiles() {*

  •  if (diceIsClosing) {*
    
  •  	return; // we want to ensure it's not possible to run this method again, so we don't run the delay method more that once every time*
    
  •  }*
    
  •  // prevent our player from selecting new tiles*
    
  •  diceIsClosing = true;*
    
  •  // Change the sprite on all selected tiles*
    
  •  for (int i = 0; i < selectedTiles.Count; i++) {*
    

_ selectedTiles*.sprite = tilecolors[1];_
_
}*_

* // Close dice after some delay*
* StartCoroutine(CloseDice());*
* }*

* IEnumerator CloseDice() {*
* yield return new WaitForSeconds(closeDiceDelay);*

* // Clear the list of selected tiles, so that it is ready to add new tiles*
* selectedTiles.Clear();*

* // let our players select tiles again*
* diceIsClosing = false;*
* }*
}

Hi @niiicolai,

First of all, thank you very much. This is the method I’ve been looking for. But I still have a question about dice part. I have 3 steps;

  1. I need player to select the tiles
    (which your code is perfectly doing
    the job),
  2. Then player will press
    roll dice button and my script will
    be activated and generates a random
    number
  3. Finally, below function will
    get the rolled dice (2,3,4,…12)
    and decides whether or not to change
    the tile color.

I am failed to understand your diceIsClosing method, sorry :frowning:


void DoSomethingWithSelectedTiles() {
 
         if (diceIsClosing) {
             return; // we want to ensure it's not possible to run this method again, so we don't run the delay method more that once every time
         }
 
         // prevent our player from selecting new tiles
         diceIsClosing = true;
 
         // Change the sprite on all selected tiles
         for (int i = 0; i < selectedTiles.Count; i++) {
             selectedTiles*.sprite = tilecolors[1];*

}

// Close dice after some delay
StartCoroutine(CloseDice());
}