I’m making an Airport Tycoon kind of game, and I’ve had this bug in my code for a few days now and I just can’t figure it out. This is a bit of a long one, but hopefully someone can find what I’m doing wrong.
Here’s what I’m doing: I’m trying to make it so that when you build one section of taxiway over another one, it removes the meshes of the underlying building. I was originally using individual GameObjects for each tile, but this was too slow, so I now have meshes for each tile that I’m combining inside one GameObject. I store them in a list with the references of each submesh contained within each tile, and then have a method for deleting specific tiles in a rectangular shape.
Here’s the code of the building:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
public class MultiMesh : MonoBehaviour {
public Vector3 startPos;
public float endDistance;
public SectionMap midSection;
public SectionMap endSection;
public Material[] materialArray;
public bool endSameAsMid = true;
private Vector3 endPos;
private List<CombineInstance> combine;
private List<Material> materials;
private MeshFilter meshFilter;
private MeshRenderer meshRenderer;
private List<List<int>> tileSubMeshList;
private int tileSize;
private int tileLength;
private float gridOffset;
Vector3 scale;
// Use this for initialization
void Awake () {
scale = new Vector3(1, 1, 1);
tileSize = GameObject.FindGameObjectWithTag("tile manager").GetComponent<TileMap>().tileSize;
meshFilter = gameObject.GetComponent<MeshFilter>();
meshRenderer = gameObject.GetComponent<MeshRenderer>();
materials = new List<Material>();
meshFilter.mesh = new Mesh();
combine = new List<CombineInstance>();
tileSubMeshList = new List<List<int>>();
}
void Start () {
gridOffset = - midSection.XSize / 2 * tileSize;
if (midSection.XSize % 2 == 0) {
gridOffset += tileSize / 2;
}
transform.localPosition = new Vector3(transform.localPosition.x + gridOffset, 0, 0);
endPos = Vector3.forward * endDistance;
tileLength = 0;
int numberOfSections;
if (endSameAsMid) {
BuildSection(midSection, startPos);
numberOfSections = (int)((Vector3.Distance(startPos, endPos) / tileSize) - midSection.ZSize) / midSection.ZSize;
tileLength += midSection.ZSize;
}
else {
BuildSection(endSection, startPos);
numberOfSections = (int)((Vector3.Distance(startPos, endPos) / tileSize) - endSection.ZSize) / endSection.ZSize;
tileLength += endSection.ZSize;
}
for (int i = 1; i <= numberOfSections; i++) {
BuildSection(midSection, new Vector3(startPos.x, 0, startPos.z + (i * midSection.ZSize * tileSize)));
tileLength += midSection.ZSize;
}
if (startPos != endPos) {
if (endSameAsMid) {
BuildSection(midSection, endPos);
tileLength += midSection.ZSize;
}
else {
BuildSection(endSection, endPos);
tileLength += endSection.ZSize;
}
}
meshRenderer.materials = materials.ToArray();
meshFilter.mesh.CombineMeshes(combine.ToArray(), false, true);
}
public void Test () {
RemoveRect (new Vector3 (20, 0, 10), new Vector3(50, 0, 100));
}
// Remove rectangle of from the mesh, this doesnt quite work properly at certain rotations
public void RemoveRect (Vector3 min, Vector3 max) {
Debug.DrawRay(transform.TransformPoint(min), Vector3.up * 100, Color.red, 1000f, false);
Debug.DrawRay(transform.TransformPoint(max), Vector3.up * 100, Color.red, 1000f, false);
Vector3 oldMin = min;
Vector3 oldMax = max;
if (min.x > max.x) {
min.x = oldMax.x ;
max.x = oldMin.x;
}
if (min.z > max.z) {
min.z = oldMax.z;
max.z = oldMin.z;
}
min = min / tileSize;
max = max / tileSize;
Debug.DrawRay(transform.TransformPoint(min * tileSize), Vector3.up * 100, Color.blue, 1000f, false);
Debug.DrawRay(transform.TransformPoint(max * tileSize), Vector3.up * 100, Color.blue, 1000f, false);
if (min.x < midSection.XSize && min.z < tileLength && max.x >= 0 && max.z >= 0){
min.x = Mathf.Clamp(min.x, 0, midSection.XSize - 1);
max.x = Mathf.Clamp(max.x, 0, midSection.XSize - 1);
min.z = Mathf.Clamp(min.z, 0, tileLength - 1);
max.z = Mathf.Clamp(max.z, 0, tileLength - 1);
Debug.Log (min.ToString());
Debug.Log (max.ToString());
for (int i = (int)min.x; i <= max.x; i++){
for (int j = (int)min.z; j <= max.z; j++) {
int[] subMeshes = tileSubMeshList[i + midSection.XSize * j].ToArray();
for (int k = 0; k < subMeshes.Length; k++) {
meshFilter.mesh.SetTriangles(new int[0], subMeshes[k]);
}
}
}
}
}
public void BuildSection (SectionMap section, Vector3 pos) {
for (int i = 0; i < section.tiles.Count; i++){
List<int> newTileSubs = new List<int>();
for (int j = 0; j < section.tiles*.tile.subMeshCount; j++){*
-
CombineInstance newCombine = new CombineInstance();*
_ newCombine.mesh = section.tiles*.tile;_
_ Vector3 newPos = pos + new Vector3((i % midSection.XSize) * tileSize, 0, - (i / midSection.XSize) * tileSize);_
_ Quaternion newRotation = new Quaternion();_
_ switch (section.tiles.rotation){
case CardinalRotation.up:
newRotation = Quaternion.LookRotation(Vector3.forward);
break;
case CardinalRotation.right:
newRotation = Quaternion.LookRotation(Vector3.right);
break;
case CardinalRotation.down:
newRotation = Quaternion.LookRotation(Vector3.back);
break;
case CardinalRotation.left:
newRotation = Quaternion.LookRotation(Vector3.left);
break;
}
newCombine.transform = Matrix4x4.TRS (newPos, newRotation, scale);
newCombine.subMeshIndex = j;
newTileSubs.Add(combine.Count);
combine.Add(newCombine);
Material newMaterial = materialArray[j];
materials.Add (newMaterial);*_
* }*
* tileSubMeshList.Add(newTileSubs);*
* }*
* }*
}
and here’s where it gets called by the builder object:
foreach (GameObject building in buildings){
_ Vector3 localMin = building.transform.InverseTransformPoint(new Vector3(coords.minX + 1, 0, coords.minZ + 1) * gridSize);
Vector3 localMax = building.transform.InverseTransformPoint(new Vector3(coords.maxX, 0, coords.maxZ) * gridSize);
* building.GetComponent().RemoveRect(localMin, localMax);
//building.GetComponent().Test ();
}*
So, here’s the really weird part: If I call the currently commented out Test() method, it works as intended, however the line just above that, using the exact same Vector3s, does what I show in the above screenshot, it removes a rectangle offset by one tile. It only does this on taxiway built from left to right. It also has some similar weirdness on both horizontal directions towards the start of the section. What I can’t get my head around is how feeding the exact same numbers into my method works in the test method, and not in the actual one. Does anyone have any idea what is going wrong?_