How to destroy Terrain-Tree-Collider?
Hey guys!
I am using a chop-wood-from-terrain-trees-script. All working fine but there is on thing i dont get. After a tree is destroyed, the collider still exist (invisible). Any ideas? :(
public class TreesManager : MonoBehaviour
{
public int TreeHP = 200;
public int DropNum = 10;
public float DropArea = 3;
public Terrain terrain;
public float BlastArea = 0.5f;
public GameObject WoodDrop;
public float ResetTime = 600;
private List<int> RemovedIndexList = new List<int>();
private SceneManager sceneManage;
private List<Logger> Loggers = new List<Logger>();
private TreeInstance[] treesBackup;
private int ChopIndex;
private bool hited = false;
private float timeTemp;
void Start()
{
sceneManage = (SceneManager)GameObject.FindObjectOfType(typeof(SceneManager));
if (sceneManage)
{
if (Network.isClient)
{
sceneManage.GetInitializeeScene();
}
}
if (terrain == null)
terrain = this.GetComponent<Terrain>();
timeTemp = Time.time;
BackupTree();
}
void Update()
{
hited = false;
if (Time.time >= ResetTime + timeTemp)
{
if (Network.isServer || Network.isClient)
{
if (Network.isServer)
{
if (sceneManage)
sceneManage.ResetAllTrees();
}
}
else
{
ResetTrees();
}
timeTemp = Time.time;
}
}
public void ResetTrees()
{
RemovedIndexList.Clear();
Loggers.Clear();
terrain.terrainData.treeInstances = treesBackup;
}
bool LoggerChecker(int index)
{
// we cannot put HP variable to every trees in the scene
// so we have to use something to define it by Index of a tree
// a Logger using for define a HP to each trees
foreach (Logger logger in Loggers)
{
if (logger.index == index)
return false;
}
Logger newLogger = new Logger();
newLogger.index = index;
newLogger.HP = TreeHP;
Loggers.Add(newLogger);
return true;
}
bool LoggerApplyDamage(int damage, int index)
{
// apply damage to a tree
if (!LoggerChecker(index))
{
foreach (Logger logger in Loggers)
{
if (logger.index == index)
{
logger.HP -= damage;
if (logger.HP <= 0)
{
return true;
}
}
}
}
return false;
}
public void Cuttree(Vector3 position, int damage)
{
if (terrain == null)
return;
// we cannot specific a tree, we just find possibility around the position
int index = 0;
foreach (TreeInstance tree in terrain.terrainData.treeInstances)
{
Vector3 treepos = Vector3.Scale(tree.position, terrain.terrainData.size) + Terrain.activeTerrain.transform.position;
var distance = Vector3.Distance(new Vector3(treepos.x, position.y, treepos.z), position);
// hit a tree if in ranged
if (distance < BlastArea)
{
if (LoggerApplyDamage(damage, index))
{
Drop(position);
RemovedIndexList.Add(index);
SendARemovedTree(index);
return;
}
}
index++;
}
}
public void SendARemovedTree(int index)
{
if (!Network.isServer && !Network.isClient)
{
// in single player
RemoveATrees(index);
}
else
{
if (Network.isServer)
{
RemoveATrees(index);
// only server can send a removed tree index;
if (sceneManage)
sceneManage.SendRemovedTreeIndex(index);
}
}
}
public string GetRemovedTrees()
{
// convert array to string using for send via RPC network
string arraylist = "";
foreach (int index in RemovedIndexList)
{
arraylist += index + ",";
}
return arraylist;
}
public void UpdateRemovedTrees(string indexremoved)
{
// get all indexes of removed trees as a string
if (terrain == null)
return;
RemovedIndexList.Clear();
// convert them to array
string[] indexes = indexremoved.Split(","[0]);
for (int i = 0; i < indexes.Length; i++)
{
int res = -1;
if (int.TryParse(indexes[i], out res))
RemovedIndexList.Add(res);
}
// save them to a removed index list
List<TreeInstance> instancesTmp = new List<TreeInstance>(terrain.terrainData.treeInstances);
foreach (int removed in RemovedIndexList)
{
// loop a removed index list find and remove a tree
instancesTmp.RemoveAt(removed);
}
// replace a tree instances in terrain data with new array
terrain.terrainData.treeInstances = instancesTmp.ToArray();
}
public void RemoveATrees(int index)
{
// remove a specific tree by index
List<TreeInstance> instancesTmp = new List<TreeInstance>();
int i = 0;
foreach (TreeInstance tree in terrain.terrainData.treeInstances)
{
// loop a all of a tree on terrain
if (i != index)
{
// basically add every tree to a Tmp array, Except a tree with a specfic index
instancesTmp.Add(tree);
}
i++;
}
// replace a tree instances in terrain data with a Tmp array
terrain.terrainData.treeInstances = instancesTmp.ToArray();
}
public void OnHit(DamagePackage dm)
{
if (!hited)
{
if (Network.isServer || (!Network.isClient && !Network.isServer))
{
Cuttree(dm.Position, dm.Damage);
hited = true;
}
}
}
public void Drop(Vector3 position)
{
// drap a wood
if (WoodDrop == null)
return;
for (int i = 0; i < DropNum; i++)
{
if (Network.isClient || Network.isServer)
{
if (Network.isServer)
Network.Instantiate(WoodDrop, DetectGround(position + new Vector3(Random.Range(-DropArea, DropArea), 0, Random.Range(-DropArea, DropArea))), WoodDrop.transform.rotation, 2);
}
else
{
GameObject.Instantiate(WoodDrop, DetectGround(position + new Vector3(Random.Range(-DropArea, DropArea), 0, Random.Range(-DropArea, DropArea))), WoodDrop.transform.rotation);
}
}
}
Vector3 DetectGround(Vector3 position)
{
RaycastHit hit;
if (Physics.Raycast(position, -Vector3.up, out hit, 1000.0f))
{
return hit.point;
}
return position;
}
void BackupTree()
{
if (terrain == null)
return;
// create backup trees data/
treesBackup = terrain.terrainData.treeInstances;
}
void OnApplicationQuit()
{
// Importance!! Need to restore all tree before close
// if not, all the removed trees will be lose forever
if (terrain == null)
return;
terrain.terrainData.treeInstances = treesBackup;
}
}
public class Logger
{
public int index;
public int HP;
}
Answer by kirby4tw · Nov 23, 2015 at 09:20 AM
Doesnt work because the "tree" / index isnt a GameObject.
Answer by say_forever · Nov 23, 2015 at 12:27 PM
Destroy(GetComponent<Terrain>());
Destroy(GetComponent<TerrainCollider>());
hope this is what you need
It depends on where you what to destroy those component.
Answer by Reefer · May 23, 2016 at 04:55 PM
public void RemoveATrees (int index)
{
// remove a specific tree by index
List<TreeInstance> instancesTmp = new List<TreeInstance> ();
int i = 0;
foreach (TreeInstance tree in terrain.terrainData.treeInstances) {
// loop a all of a tree on terrain
if (i != index) {
// basically add every tree to a Tmp array, Except a tree with a specfic index
instancesTmp.Add (tree);
}
i++;
}
// replace a tree instances in terrain data with a Tmp array
terrain.terrainData.treeInstances = instancesTmp.ToArray ();
// refresh the terrain, get rid of collider of that tree.
float[,] heights = terrain.terrainData.GetHeights(0, 0, 0, 0);
terrain.terrainData.SetHeights(0, 0, heights);
}
I don't know if you need that anymore but change your RemoveATrees to that and it works.
Your answer
Follow this Question
Related Questions
Hi guys, I need help with C# Scripting using Raycast. 1 Answer
Modeling a harvester: collider or distance? 0 Answers
GameObject not colliding properly with a collider! 3 Answers
OnTriggerExit does not work 0 Answers
When raycasting, script doesn't detect anything coming into ray yet I did everything right! 1 Answer