Error on: terraindata.RecalculateTreePositions();

I have been using scripts in 2.6 without probs - they are throwing this error in 3.0 - anything I can do to fix this?

Assets/Unity Terrain Tools/treeProperties.js(124,21): BCE0120: ‘UnityEngine.TerrainData.RecalculateTreePositions’ is inaccessible due to its protection level.

Yes, remove the call and functionality.
You can no longer use it. But I guess you were aware that this day might come as UT warned countless times that undocumented api is undocumented cause it can change and vanish at any time … they even left it there till the next major :slight_smile:

ha ok I see :slight_smile:

I wonder if there is any other way of achieving the functionality I was using - the ability to remove all trees below a certain height - below the water level.

Also, this one is more of a wishlist I guess … when using the Place Tree tool would it not be more realistic to allow for random rotation of trees each time one is placed? A row of willowtrees with identical rotation can look a little strange :slight_smile:

Here is the code I was using to remove trees below the waterline. Can anyone see a way of this working now that we can’t use RecalculateTreePositions:

var vegHeight : float;

function Start(){
	vegHeight=transform.position.y;
	RemoveTrees();
}
function RemoveTrees(){
terraindata = Terrain.activeTerrain.terrainData;
	terrain = Terrain.activeTerrain;
	var instances : ArrayList = new ArrayList();
	for(var i : int = 0; i < terraindata.treeInstances.length; i++){
		var instance  : TreeInstance = new TreeInstance(); 
		instance = terraindata.treeInstances[i]; 
		var pos =  instance.position;
		pos = terrain.gameObject.transform.position + Vector3(pos.x * terraindata.size.x, pos.y * terraindata.size.y, pos.z * terraindata.size.z);
		if(terrain.SampleHeight(pos) > vegHeight){
			instances.Add(instance);
		}
	}
	terraindata.treeInstances = new TreeInstance[instances.Count]; 
	terraindata.treeInstances = instances.ToArray(typeof(TreeInstance)); 
	//terraindata.RecalculateTreePositions(); 

}

This works (C#):

			//Clear Trees
			TreeInstance[] newtrees = new TreeInstance[0];
			terrainData.treeInstances = newtrees;

			//Check Existing Trees (should be none)
			for (int i = 0 ; i < terrainData.treeInstances.Length; i ++) {
				TreeInstance t = terrainData.treeInstances[i];
				Debug.Log( System.String.Format("TreeInstance {0} {1} {2} {3} {4}",i,t.position.ToString(),t.widthScale,t.heightScale,t.prototypeIndex));


			}

			//Add a Tree
			TreeInstance ti = new TreeInstance();
                       //position ranges from 0 to 1 and x and z are flipped from the world space
			ti.position = new Vector3(Random.value,0,Random.value);
			ti.widthScale = 1;
			ti.heightScale = 1;
			ti.color = new Color(1,1,1);
			ti.prototypeIndex = 0;
			_terrain.AddTreeInstance(ti);

			//commit changes
			_terrain.Flush ();

Anyone know how to add rotation around y to the dang things?

TreeInstance ti = new TreeInstance();
    //position ranges from 0 to 1 and x and z are flipped from the world space
    ti.position = new Vector3(Random.value,0,Random.value);

Problem:
I’ve figured out that X and Z are flipped for tree rendering position only. But if you have colliders on trees, X and Z for colliders are not flipped. So you can pass through visible trees but run into invisible obstacles in places where there are no trees.

Billboarding is the reason the terrain engine does it like this. Not likely to change very soon.

I am not using them as colliders so I can;t confirm, but that sounds like a bug.

I haven’t been able to get colliders to work at all with script-generated trees. The weird thing is that if I stop my game and then play it again without the tree-generating script running, those same colliderless trees now have colliders. I can’t figure it out.

I’m a bit confused. I have created a new test project with a terrain and a simple tree planting script on it and it works fine. X and Z are not flipped neither for trees, neither for colliders.

http://autosim-utilities.ru/unity/AddTreeInstance/WebPlayer.html

using UnityEngine;

public class PlaceTrees : MonoBehaviour
{

    void Start()
    {
        var terrain = (Terrain)FindObjectOfType(typeof(Terrain));
        terrain.terrainData.treeInstances = new TreeInstance[0];

        for (float x = 0; x < 1; x += 0.1f)
        {
            var treeInstance = new TreeInstance
                               {
                                   prototypeIndex = 0,
                                   position = new Vector3(x, 0, 0.5f),
                                   heightScale = 1f,
                                   widthScale = 1f,
                                   lightmapColor = Color.white,
                                   color = Color.white,
                               };
            terrain.AddTreeInstance(treeInstance);
        }

    }
}

getting close …

This code below is working well to remove all trees and then populate new random trees but how would we make sure that the new trees are populated only if they are higher than the current water height?

Ah GOT IT!!!

Take my code above - 4th post from the top and change:

terraindata.RecalculateTreePositions();

… to …

terrain.Flush ();

and that’s it - all trees will be removed below the water height. Just place the script on the water.

I have this problem too. After the scene starts, colliders don’t work. But recently I did some runtime terrain modification experiments and noticed that this code somehow magically forces colliders to work.

var terrain = (Terrain)FindObjectOfType(typeof(Terrain));
terrain.terrainData.SetHeights(0, 0, new float[0, 0]);

I don’t know why it happens because this code does nothing useful.

Yeah I used that same bit of code to force the Trees back to the proper height. I figured that out after noticing in the IDE that the trees would auto-adjust themselves to appropriate heights when you edited the terrain… it makes sense because obviously Unity has to call the internal RecalculateTreePositions() whenever the heightmap is edited. That kinda sucks in a way because it means that anytime you alter a terrain that has lots of trees Unity will have to go through a long process of recalculating tree positions, even ones in areas unaffected by the height change.

I did discover the answer to my particular collider problem though. I shared it in another thread but I will mention it here too in case anyone is reading this with the same issue: You must use terrain.AddTreeInstance() to add a tree, you can’t just alter the treeInstances array which is a property of terrainData.

So remember, always use AddTreeInstance() or else your new tree wont get a collider!