Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to distinguish between trees and terrain in collision

Discussion in 'Editor & General Support' started by Jim Offerman, Jan 24, 2010.

  1. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    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... :(
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    Maybe a duplicate of the first terrain with no trees and no renderer, just the terrain collider.

    --Eric
     
  3. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    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.
     
  4. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,400
    If you're testing and you hit the "no trees" terrain and not the "trees" terrain, doesn't that do the same thing?

    I don't think functions like Terrain.SetNeighbors would exist if there were any such mantra. ;)

    --Eric
     
    Skunk-Software likes this.
  5. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    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.
     
  6. Tom163

    Tom163

    Joined:
    Nov 30, 2007
    Posts:
    1,272
    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.
     
  7. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    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 :)
     
  8. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    Testing against the positions of the trees alone is not sufficient for my purpose.

    For clarity, here's how my placement algorithm works:
    1. Raycast from the mouse position to determine a "placement point" on the terrain.
    2. 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.
    3. 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! :)
     
  9. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    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?
     
  10. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    the rigidbody requirement is no problem. Just remote the rigidbody component altogether from the object as you detect the collision :)
     
  11. Jim Offerman

    Jim Offerman

    Joined:
    Jul 17, 2009
    Posts:
    177
    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.
     
  12. ssls

    ssls

    Joined:
    Aug 26, 2020
    Posts:
    2
    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.
     
    Gilderdale96 and noio like this.
  13. Gilderdale96

    Gilderdale96

    Joined:
    Aug 10, 2018
    Posts:
    4
    Very nice! Terrain.SampleHeight() :D
     
  14. Sourabh_PTW

    Sourabh_PTW

    Joined:
    Mar 7, 2022
    Posts:
    33
    what if I have some other objects also?