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
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.