How do I reference a GameObject after finding its collider with Physics.OverlapSphere()?

Currently I have a Player game object placed in the scene with a script that generates TerrianCubes (just built in Cubes) underneath the player, places some other WorldFeatures (spheres) randomly around the scene, and then places TerrainCubes forming a path connecting that WorldFeature back to the player. It’s rudimentary. The path isn’t always player navigable, but it does what I want which is to start the scene with a bunch of Terrain Cubes connecting WorldFeatures back to the Player.

Now I’m trying to add a script to the TerrainCubes so that they instantiate with different colors. My goal is to have TerrainCubes with no neighbors start with a random color and for those with neighbors to derive their color from those neighbors. The code runs (I can play the Scene), but only a few blocks around the Player change color and I get this error msg (“NullReferenceException: Object reference not set to an instance of an object.”)

Here’s the DefineTerrainScript I’m using for that:

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

public class DefineTerrainScript : MonoBehaviour {

	int rColor = 0,
		gColor = 0,
		bColor = 0,
		aColor = 0;

	Collider[] hitTerrainCubes = Physics.OverlapSphere(new Vector3(0.5f,0.5f, 0.5f), 1f);

	// Use this for initialization
	void Start () {

		if (hitTerrainCubes.Length == 0){

			rColor = Random.Range (0,3);
			gColor = Random.Range (0,3);
			bColor = Random.Range (0,3);
			aColor = Random.Range (0,3);

		}
		else {

			for (int i = 0; i < hitTerrainCubes.Length; i++){

				GameObject hitTerrainCube = hitTerrainCubes*.transform.gameObject;*
  •  		rColor += hitTerrainCube.GetComponent<DefineTerrainScript>().rColor;*
    
  •  		gColor += hitTerrainCube.GetComponent<DefineTerrainScript>().gColor;*
    
  •  		bColor += hitTerrainCube.GetComponent<DefineTerrainScript>().bColor;*
    
  •  		aColor += hitTerrainCube.GetComponent<DefineTerrainScript>().aColor;*
    
  •  	}*
    
  •  }*
    
  •  this.gameObject.renderer.material.color = new Color(rColor%4,*
    
  •                                                      gColor%4,*
    
  •                                                      bColor%4,*
    
  •                                                      aColor%4);*
    
  • }*
    * I had some trouble finding the center and radius of the current TerrainCube to use for Physics.OverlapSphere so I just put in fixed numbers for now :frowning:
    My understanding is that the TerrainCubes will instantiate in order, so that later TerrainCubes will be able to see earlier ones. Here’s my GenerateTerrainScript for reference:

  • public GameObject terrainCube;*

  • public GameObject player;*

  • public float gridX;*

  • public float gridZ;*

  • public float spacing;*

  • public int startingFeatures;*

  • public GameObject worldFeatures;*

  • public float worldSize;*

  • // Use this for initialization*

  • void Start () {*

_ Vector3 playerStart = new Vector3(player.transform.position.x, player.transform.position.y, player.transform.position.z) * spacing;_

  •  AddInitialTerrain(playerStart);*
    
  •  for (int i = 0; i < startingFeatures; i++){*
    
  •  	Vector3 pos = (Vector3)PlaceWorldFeatures(worldFeatures);*
    
  •  	AddInitialTerrain(pos);*
    
  •  	ConnectAtoB(pos, playerStart);*
    
  •  }*
    
  • }*

  • // Update is called once per frame*

  • void Update () {*

  •  //SearchForThisHere(emptySpaces, player);*
    
  •  //FillEmptySpace();*
    
  • }*

  • // Adds terrain around worldFeatures at start of new level*

  • private void AddInitialTerrain(Vector3 pos){*

  •  pos.x -= (int)(gridX/2);*
    
  •  pos.y--;*
    
  •  pos.z -= (int)(gridX/2);*
    
  •  for(int z = 0; z < gridZ; z++){*
    
  •  	for(int x = 0; x < gridX; x++){*
    
  •  		Vector3 placeHere;*
    
  •  		placeHere.x = pos.x + x;*
    
  •  		placeHere.y = pos.y;*
    
  •  		placeHere.z = pos.z + z;*
    
  •  		Instantiate(terrainCube, placeHere, Quaternion.identity);*
    
  •  	}*
    
  •  }*
    
  • }*

  • // Instantiates worldFeatures and returns position for adding terrain around.*

  • private Vector3? PlaceWorldFeatures(GameObject placeThis){*

  •  Vector3 pos = new Vector3(Mathf.Round(Random.Range(-worldSize, worldSize)),*
    
  •                            Mathf.Round(Random.Range(-worldSize, worldSize)),*
    

_ Mathf.Round(Random.Range(-worldSize, worldSize))) * spacing;_

  •  Instantiate(placeThis, pos, Quaternion.identity);*
    
  •  return pos;*
    
  • }*

  • private void ConnectAtoB(Vector3 a, Vector3 b){*

  •  Vector3 newB = new Vector3(b.x-1, b.y-1, b.z-1);*
    
  •  while(a != newB){*
    
  •  	if(a.x < newB.x){a.x++;}*
    
  •  	if(a.x > newB.x){a.x--;}*
    
  •  	if(a.y < newB.y){a.y++;}*
    
  •  	if(a.y > newB.y){a.y--;}*
    
  •  	if(a.z < newB.z){a.z++;}*
    
  •  	if(a.z > newB.z){a.z--;}*
    
  •  	Instantiate(terrainCube, a, Quaternion.identity);*
    
  •  }*
    
  • }*
    Comments about best practices, optimization, and alternative code are appreciated.

You need to move the OverlapSphere() into Start(). That is you declare the variable:

 Collider[] hitTerrainCubes;

Then in Start():

 hitTerrainCubes = Physics.OverlapSphere(new Vector3(0.5f,0.5f, 0.5f), 1f);

While you appear to be doing everything in Start(), any time object move or are removed, you need to call OverlapSphere() again.