Is there a way to distinguish between the terrain and the trees that are placed on it (using Unity’s built-in tree system)?
It appears as though Unity treats the terrain and the trees on it as a single entity with regards to collision detection and raycast, which is inconvenient for me, since I want to allow the player to place buildings on top of the terrain but not on top of trees, for obvious reasons
Anyway to work around this? I’ve tried unchecking “Create Tree Colliders” and using a tree prefab with its own collider, but that doesn’t seem to work…
This would solve part of my problem, but not all of it. I also need to be able to test against just the trees to determine if you’re building on clear ground.
Also, doesn’t this go against the whole “There Shall Be Only One Terrain” mantra of the Unity engine?
Thinking about it some more, all I really need would be for the tree colliders to be in a different layer from the terrain mesh collider.
Yep, that would work for raycasts. Unfortunately, I also need full collision between the to-be-placed building and the trees-but-not-the-terrain
BUT!
I have an idea:
no tree colliders on the terrain
-place an empty game object with a collider attached at all the positions where the terrain renders a tree
The second bit may be a little tedious, so I may want to do that using a script (if that’s at all possible). On the other hand, doing it by hand I could probably throw a single collider about a whole bunch of trees, making the whole thing more efficient.
Instead of using collisions, you can also test against the positions of all trees. They’re stored in the terrain data, you just need to scale them to world coordinates.
that will not work anyway as long as you don’t drop the building vertically down to find the collision (just placing it will not cause a single collision to fire)
And if you do that, the distinction between terrain and trees is easy. If you have the collision point, get the terrain height for that point and compare
Testing against the positions of the trees alone is not sufficient for my purpose.
For clarity, here’s how my placement algorithm works:
Raycast from the mouse position to determine a “placement point” on the terrain.
Put a trigger volume on the “placement point” and use OnTriggerStay() to determine if there are any obstructions in the way - i.e. other buildings, trees, etc.
If no obstructions found, place building on the “placement point”.
I’ll try Dreamora’s suggestion of comparing the collision point against the terrain height. Seems like the easiest route to follow at this point!
This was a nice idea, but unfortunately it doesn’t really work in practice:
OnTriggerStay() doesn’t give you a contact point to work with
OnCollisionStay() is only called for collisions when at least one of the colliders is also a non-kinematic rigidbody.
Since it is obviously undesirable for the terrain (including the trees) to be a rigidbody, the non-kinematic would have to be my placement volume… but if I make my placement volume non-kinematic, the physics system will start pushing it out of the terrain in response to the collision, which is something I definitely don’t want.
So… back to square one! Any other ideas I can try?
Yup, and then it works for 1 frame… what about the next?
I suppose I could make it so that the rigidbody is added on each OnFixedUpdate() and then removed on the subsequent call to OnCollisionEnter/Stay, but that feels like I’m fighting the system rather than using it.
You could just do a raycast, check if it’s whatever tag your terrain is, and then just check if the collision point is higher than height of the terrain.