- Home /
Picking Trees with Mouse
Hello Everyone,
I've been trying this for a few days, but seems I'm unable to undestand some concepts or I'm missing something on terrain trees, so I need the help from my fellow forum colleagues.
Let's say I have a terrain, and in this terrain, I generated several trees. I activate the Tree Collider option in the terrain, and added a capsule collider to the prefab. When putting a Character Controller in my camera, it does collide with the tree and I can't walk through the tree.
Now I want to click on my screen and select a tree, so I thought, seems a good use for raycast, then I did it, but all I get is a reference to the Terrain object. I read somewhere that Unity bakes all my tree colliders with the Terrain collider, and that's why I'm getting only references to the terrain. Then I thought, okay, I need to check the position where the ray crossed the terrain, and verify if there's a tree by serching the TreeInstances[] object. The problem is, doing that is VERY imprecise. If I just compare with the position in the ray, I must click too exactly and this makes me click like hell to select a tree, and if I put some x and z tolerance, I can end selecting several trees at once, and that's not desired.
Is there a way I can achieve that (clicking and getting the tree I tried to click) correctly? Thanks in advance.
zharramadar:
It may help if you tell us "why" you are doing this.
Is this in edit time? Or at run time? And why do you need to find out which tree you've selected?
I am doing this for a RTS game I'm doing. I want to populate the world with trees, and I want to be able to select a particular tree and send a troop to it so it can chop it down and start gathering wood. When clicking a tree with a gatherer selected, it should go to the tree and chop it down (which will remove the treeinstance and place a tree mesh in the place so it can fall down). For that reason, I need to pick one and just one tree. And it is at runtime.
Oh, btw, I found a demo from $$anonymous$$'s (which later made the $$anonymous$$ Terrain Tools) where you walk and instance explosions, and then trees fall down, and he's using kinda of what I did so far, but it doesn't count for accuracy, as he's destroying an entire area, and I can do it so far for an area, but I need to pinpoint trees).
Sure.
The topic I found it: http://forum.unity3d.com/threads/28855-Destroyable-Trees
The demo itself: http://web.lemuria.org/~tom/unity/BlastingTrees.html
Answer by Adam-Buckner · Sep 09, 2011 at 10:16 PM
I've only peeked at these. Do you need a specific tree? Can you send your unit to an area and have the unit just find the closest tree? Or do you really need to have the units chop specific trees down?
I'm thinking that your choice of picking a ray on the terrain and iterating position would be good. Is there an easy way for you to make your precision a little more "fuzzy"?
The other option that occurred to me was at Start(), iterate thru all of the trees and add a collider to each tree location, probably with some viable offset to put the collider where you need it to be. I only hesitate in suggesting this as there could be thousands of trees in your game, and this could be a performance problem. I also am unclear how best to deal with getting a collider to relate to a specific tree without an instance of a script on each one - again unclear how this would effect performance. eg: Iterate thru trees. Add GameObject with collider and script. Set value on script to point to this tree and reference collisions from this collider.
Or not use the terrain engine to place your trees... but then I'd suppose you'd lost the LOD system, and other terrain optimizations...
What is interesting to note is that (iirc) that these trees don't literally exist in the same way as other objects, do they? They are in game representations of locations on a splat map, no?
I'll try here with putting the terrain colliders. I'm using P|Terrain here so I may have tons of trees in the terrains, and maybe hurt some performance, but I'll check it and let you know. Not using the terrain engine to place the trees would be not feasible due to the amount of trees involved in the process. I'll play a bit more with the ray and tree position to see if I can get better results as well. I'll keep you posted, and thanks =D
What does occur to me is that you might be able to write an editor script that places trees at random around a mouse click and sets them into the terrain. This might be a way to go. Then you wouldn't need to place the trees by hand. You could simulate your own tree brush...
$$anonymous$$y trees are already generated and populated into the terrains, it comes from a tree placement map generated in World $$anonymous$$achine 2 and imported into Unity with the mass terrain importer tool from P|Terrain extension. I need to do exactly the opposite, I need to select and erase trees, and not in an area, but EXACTLY on a tree. I messed up around with the click tolerance in my script, but can't make it nice. I'll try now with creating colliders when the terrain is loaded.
Answer by zharramadar · Sep 11, 2011 at 03:36 AM
Well, so far I couldn't get it to select one tree, and placing a collider for each tree by script was indeed a performance problem, so I can't follow that route. I'll plan using for my game something like Rise of Nations wood gathering system, although this will take away a bit of the realism I wanted for it.
I'll leave the question open in case anyone got a tip or a full solution to that.
Out of curiosity: was the performance hit in the set up phase, or when selecting a tree?
In the set up phase, and by using the paged terrain solution I'm using, having it there anytime a terrain is being displayed can be bad.
Answer by jc_lvngstn · Oct 23, 2011 at 10:53 PM
I've been experimenting with the same challenge. Here are some thoughts.
I want to be able to detect mouse clicks on trees, bushes, heck maybe even grass. Since Unity considers all trees and such as part of the terrain, the first trick is to decide if we have selected the terrain or not.
If we get the collision point from a raycast, axe strike, whatever, if we can determine the terrain height at that point, we can know if we hit the terrain or not. If the hit point is a meter above the ground...well, we must not have hit the ground, so it's a tree or something.
Once we do that...it means searching through all trees and such to see what we hit, by finding the closest tree. I haven't tested this yet, so I don't know what kind of performance hit this will mean. The demo others have mentioned where you can blow up trees in your area seems to run VERY fast, but I don't know how many trees he has. I have a lot. But even so...it's a start. If it is a big performance problem, you could split up the trees in the map into sectors, and only compare against trees in your sector.
Just some thoughts, maybe useful, maybe not :)
[Edit] I was indeed able to do this, by casting a ray. If I hit "terrain" (which may be a tree, dirt, a detail object, grass, etc), I then used Terrain.SampleHeight to get the actual ground height beneath the ray hit location. If the ray hit height was above the ground height...I knew I hit a tree or detail object instead of the ground. At that point, I cycled through all TreeInstances and found the closest one, and remove it.
The big problem (and final hurdle that I know of) is this: It doesn't remove the tree collider!! So even though the tree is gone, the collider still exists. I don't know how to remove the collider also. So, at this point I'm going to just remove all colliders from my trees, and try to dynamically place colliders only on the trees near my character. Wish me luck, and hope that UT will someday add more support for the terrain API.
I think I'll eventually have some code that launches when the game starts, and looks at all trees and partitions them into regions...and check only the trees near my character, should speed things up. Especially if you have a lot of trees, in one scene I had about 50,000 trees and the sort algorithm took a tenth of a second...a bit much.
Answer by oxinhome · Dec 11, 2011 at 06:22 PM
hey, try this. Physics.SphereCastAll() to return the array of RaycastHit. and then still need to scan the treeInstances[], then get what tree you collid with. I think it can work.
Answer by madmike6537 · Dec 10, 2012 at 12:58 AM
Yikes this is really going to throw a hitch into my game. I was hoping to chop trees by adding a rigidbody to make them fall. Now it seems there will not be a way to do this with the current system without adding trees individually. Hmm..
Your answer
Follow this Question
Related Questions
Getting treePrototype information from RayCasting collisions onto terrain? 2 Answers
Tree collider doesn't work 0 Answers
How can I separate tree colliders from terrain colliders? 2 Answers
Unity 2017 does not update tree collider in terrain 1 Answer
Tree Colliders Not Working With Physics.CheckSphere / Capsule 4 Answers