I’m designing a game that uses “chunks” to store “blocks” similar to Minecraft.
When a block is placed down, it gets its vertices and triangles assigned, as well as the uv vertices (though I don’t think I’m doing those properly but that’s for another question). It also is assigned as a child to whichever chunk it’s in.
There is a Boolean array in the chunk that keeps track of where each block is placed based on relative position. Ex: blockPos[transform.localPosition.x, —.y, —.z]
When a block is placed it is also supposed to call a function in the parent which then calls a function in each child to re-evaluate the mesh.
My problem is that the meshes do not update when the ChunkUpdate() function is called. They work properly only on initial placement.
Below is the script attached to the Chunk Object. Below that is the script attached to the Block Object.
using UnityEngine;
using System.Collections;
public class ChunkScript : MonoBehaviour {
public bool[,,] blockPos = new bool[10,300,10];
public void ChunkUpdate() {
foreach (Transform child in transform) {
BlockScript childScript = child.GetComponent<BlockScript>();
childScript.CreateFaces();
}
}
}
Below: Script attached to block object
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class BlockScript : MonoBehaviour {
//Code for rendering mesh
Vector3[] vertices = new Vector3[8];
List<int> trianglesOne = new List<int>();
Vector2[] uvs = new Vector2[8];
Mesh mesh;
public Material wood;
//Vector3 pos;
//End of code for rendering mesh
ChunkScript chunkScript;
public GameObject CoordChecker;
int xPos;
int yPos;
int zPos;
void AddComponents() {
gameObject.AddComponent<MeshFilter>();
gameObject.AddComponent<MeshRenderer>();
gameObject.AddComponent<BoxCollider>();
BoxCollider box = gameObject.GetComponent<BoxCollider>();
box.size = new Vector3(.99f, .99f, .99f);
mesh = GetComponent<MeshFilter>().mesh;
if (GlobalVariableHolder.wood) gameObject.GetComponent<MeshRenderer>().material = wood;
gameObject.tag = "Block";
}
void Start() {
AddComponents();
}
public void printName() {
print(name);
}
void OnTriggerEnter(Collider other) {
if (other.tag == "Chunk") {
transform.parent = other.transform;
xPos = (int)transform.localPosition.x;
yPos = (int)transform.localPosition.y;
zPos = (int)transform.localPosition.z;
transform.name = (xPos + " " + yPos + " " + zPos);
chunkScript = transform.parent.GetComponent<ChunkScript>();
chunkScript.blockPos[xPos, yPos, zPos] = true;
CreateFaces();
chunkScript.ChunkUpdate();
}
}
void OnDestroy() {
chunkScript.blockPos[xPos, yPos, zPos] = false;
chunkScript.ChunkUpdate();
}
//Checks if each direction has a block and calls the respective function to draw the face
public void CreateFaces() {
mesh.Clear();
Vertices();
if (zPos < 9) {
if (chunkScript.blockPos[xPos, yPos, zPos + 1] == false) FaceNorth();
} else if(zPos == 9) {
GameObject checker = Instantiate(CoordChecker, new Vector3(xPos, yPos, zPos + 1), Quaternion.identity) as GameObject;
CoordCheckerScript checkerScript = checker.GetComponent<CoordCheckerScript>();
if (checkerScript.containsBlock == false) { FaceNorth(); }
Destroy(checker.gameObject);
}
if (xPos < 9) {
if (!chunkScript.blockPos[xPos + 1, yPos, zPos]) FaceEast();
} else if(xPos == 9) {
GameObject checker = Instantiate(CoordChecker, new Vector3(xPos + 1, yPos, zPos), Quaternion.identity) as GameObject;
CoordCheckerScript checkerScript = checker.GetComponent<CoordCheckerScript>();
if (checkerScript.containsBlock == false) { FaceEast(); }
Destroy(checker.gameObject);
}
if (zPos > 0) {
if (!chunkScript.blockPos[xPos, yPos, zPos - 1]) FaceSouth();
} else if(zPos == 0) {
GameObject checker = Instantiate(CoordChecker, new Vector3(xPos, yPos, zPos - 1), Quaternion.identity) as GameObject;
CoordCheckerScript checkerScript = checker.GetComponent<CoordCheckerScript>();
if (checkerScript.containsBlock == false) { FaceSouth(); }
Destroy(checker.gameObject);
}
if (xPos > 0) {
if (!chunkScript.blockPos[xPos - 1, yPos, zPos]) FaceWest();
} else if (xPos == 0) {
GameObject checker = Instantiate(CoordChecker, new Vector3(xPos - 1, yPos, zPos), Quaternion.identity) as GameObject;
CoordCheckerScript checkerScript = checker.GetComponent<CoordCheckerScript>();
if (checkerScript.containsBlock == false) { FaceWest(); }
Destroy(checker.gameObject);
}
if (yPos < 299) {
if (!chunkScript.blockPos[xPos, yPos + 1, zPos]) FaceTop();
}
if (yPos > 0) {
if (!chunkScript.blockPos[xPos, yPos - 1, zPos]) FaceBottom();
}
int[] triangles = trianglesOne.ToArray();
mesh.triangles = triangles;
}
//Code to set mesh triangles
void Vertices() {
vertices[0] = new Vector3(-0.5f, -0.5f, -0.5f);
vertices[1] = new Vector3(-0.5f, 0.5f, -0.5f);
vertices[2] = new Vector3(0.5f, 0.5f, -0.5f);
vertices[3] = new Vector3(0.5f, -0.5f, -0.5f);
vertices[4] = new Vector3(-0.5f, -0.5f, 0.5f);
vertices[5] = new Vector3(-0.5f, 0.5f, 0.5f);
vertices[6] = new Vector3(0.5f, 0.5f, 0.5f);
vertices[7] = new Vector3(0.5f, -0.5f, 0.5f);
mesh.vertices = vertices;
for(int i = 0; i < vertices.Length; i++) {
uvs <em>= new Vector2(vertices_.x, vertices*.z);*_</em>
}
mesh.uv = uvs;
}
void FaceNorth() {
trianglesOne.Add(7);
trianglesOne.Add(6);
trianglesOne.Add(5);
trianglesOne.Add(7);
trianglesOne.Add(5);
trianglesOne.Add(4);
}
void FaceEast() {
trianglesOne.Add(3);
trianglesOne.Add(2);
trianglesOne.Add(6);
trianglesOne.Add(3);
trianglesOne.Add(6);
trianglesOne.Add(7);
}
void FaceSouth() {
trianglesOne.Add(0);
trianglesOne.Add(1);
trianglesOne.Add(2);
trianglesOne.Add(0);
trianglesOne.Add(2);
trianglesOne.Add(3);
}
void FaceWest() {
trianglesOne.Add(4);
trianglesOne.Add(5);
trianglesOne.Add(1);
trianglesOne.Add(4);
trianglesOne.Add(1);
trianglesOne.Add(0);
}
void FaceTop() {
trianglesOne.Add(1);
trianglesOne.Add(5);
trianglesOne.Add(6);
trianglesOne.Add(1);
trianglesOne.Add(6);
trianglesOne.Add(2);
}
void FaceBottom() {
trianglesOne.Add(4);
trianglesOne.Add(0);
trianglesOne.Add(3);
trianglesOne.Add(4);
trianglesOne.Add(3);
trianglesOne.Add(7);
}
The If statements in BlockScript check for adjacent blocks inside the chunk as well as outside the chunk.
Any help is appreciated!
EDIT
I removed the mesh.clear in the ChunkScript because I clear the mesh in BlockScript.CreateFaces();
EDIT TWO
I also commented out “CreateFaces();” in BlockScript.OnTriggerEnter() because of the redundancy in calling CreateFaces() and then calling ChunkScript.ChunkUpdate() which then calls CreateFaces();
EDIT THREE
I added a call to ChunkScript.ChunkUpdate() in BlockScript.OnDestroy();
After testing with that line of code, I notice something:
Example One:
Place A down, then place B down to east of A:
A has all sides rendered,
B has all sides rendered but west side;
Example Two:
Place A down, then place B down to east of A, then delete A:
A has all sides rendered originally,
B has all sides but west rendered originally,
Upon deletion of A, B has all sides rendered;
Ah, you have to use GameObject.SetActive(bool) then. Sorry about that.
– chillersanim