I have found a solution for you using this link (in my second comment).
What this script does is move a single capsule collider around the scene to the nearest tree that the player is facing. You can give this collider a tag, and even put it on a separate layer then only raycast on that layer if you still have/want terrain tree colliders.
CREDIT : this is just a slightly modified script written by Loren Logic as found here. All I have done is changed the static variable reading the players position to a transform that is dropped in the inspector, and added a couple of Debug LogWarnings if there is no player in the inspector or no tree capsule object is found in the scene.
To Setup :
- add a capsule object to the scene, having a capsule collider and a kinematic rigidbody, named “Tree”. Disable the renderer component (or leave on to test). I also turned gravity off, and scaled the Y-axis.
- attach the following script to the terrain object named “Terrain” (or an empty GameObject, the camera, or even the tree collider object)
- drag and drop your Player object in the Inspector
the script :
// SOURCE : Loren Logic
// http://answers.unity3d.com/questions/282910/tree-collision.html#answer-406989
/*
Tree Collision?
This is a frequently asked question. The most popular answer is some derivative of the reference manual's topic, "Setting Up Tree Collisions."
That works just fine, and potentially gives every tree its own collider.
My cheapo computer has a cheapo video card in it, and I keep it that way so I am forced to optimize my games for those who also have lousy video cards.
It occurred to me that my FPS game's flying protagonist can really only hit the nearest tree, so giving every tree a collider means physics processing for every tree but one has no return on investment.
Why not move one efficient capsule collider to the nearest tree in case I smack into it?
A built-in array and a little math in a short script sped up my FPS dramatically compared to painting trees on my terrain with one probably unused capsule collider each.
I got rid of the capsule collider in my prototype tree and supplied the original colliderless tree to the terrain tool for painting onto my terrain.
I attached the following script "sctTerrain" to the terrain object named "Terrain."
I added a capsule object to the scene having a capsule collider and a kinematic rigidbody (recommended by Unity if I am going to move my collider around a lot).
I sized the capsule by hand to appropriately match the prototype tree, the top branches of which I can fly through without dying.
The capsule has its mesh renderer turned off so it is invisible but still solid. I named the capsule "Tree" so if I fly into the capsule I can report, "Tree got you."
If my script can't find any trees AND cannot find the capsule object, it destroys itself at Start() because it is unneeded.
Otherwise it places the capsule to surround the nearest tree trunk and scales it to match the tree's height less the sparse top branches.
This math-based technique for colliding with trees is fast, and I recommend it:
*/
// ****
// TO SETUP :
// add a capsule object to the scene having a capsule collider and a kinematic rigidbody, named "Tree"
// attach the following script to the terrain object named "Terrain"
// drag and drop your Player object in the Inspector
// ****
#pragma strict
public var player : Transform;
private var paryTrees : TreeInstance[];
private var pvecTerrainPosition : Vector3;
private var pvecTerrainSize : Vector3;
private var pgobTreeCollide : GameObject;
private var pvecCollideScale : Vector3;
private var pbooCollideWithTrees : boolean = false;
function Start()
{
// Get the terrain's position
pvecTerrainPosition = Terrain.activeTerrain.transform.position;
// Get the terrain's size from the terrain data
pvecTerrainSize = Terrain.activeTerrain.terrainData.size;
// Get the tree instances
paryTrees = Terrain.activeTerrain.terrainData.treeInstances;
// Get the invisible capsule having the capsule collider that makes the nearest tree solid
pgobTreeCollide = GameObject.Find("Tree"); // This is a capsule having a capsule collider, but when the flier hits it we want it to be reported that the flier hit a tree.
// Are there trees and a tree collider?
if ((pgobTreeCollide != null) && (paryTrees.length > 0))
{
// Set a flag to make this script useful
pbooCollideWithTrees = true;
// Get the original local scale of the capsule. This is manually matched to the scale of the prototype of the tree.
pvecCollideScale = pgobTreeCollide.transform.localScale;
}
// No need to use this script
else
{
Debug.LogWarning( "NO CAPSULE NAMED TREE FOUND, OR NO TERRAIN TREES, DESTROYING SCRIPT..." );
Destroy(this);
}
// has the player been assigned in the Inspector?
if ( !player )
{
Debug.LogWarning( "NO PLAYER OBJECT IN THE INSPECTOR, DESTROYING SCRIPT..." );
Destroy(this);
}
}
function Update()
{
var L : int;
var triTree : TreeInstance;
//var vecFlier : Vector3 = sctFly.svecXYZ; // My protagonist's position, passed by a static variable in a script called sctFly.
var vecFlier : Vector3 = player.position; // using the player transform, dropped in the inspector
var fltProximity : float;
var fltNearest : float = 9999.9999; // Farther, to start, than is possible in my game.
var vec3 : Vector3;
var vecTree : Vector3;
var intNearestPntr : int;
// Test the flag
if (pbooCollideWithTrees == true)
{
// Find the nearest tree to the flier
for (L = 0; L < paryTrees.length; L++)
{
// Get the tree instance
triTree = paryTrees[L];
// Get the normalized tree position
vecTree = triTree.position;
// Get the world coordinates of the tree position
vec3 = (Vector3.Scale(pvecTerrainSize, vecTree) + pvecTerrainPosition);
// Calculate the proximity
fltProximity = Vector3.Distance(vecFlier, vec3);
// Nearest so far?
if (fltProximity < fltNearest)
{
// Remember the nearest
fltNearest = fltProximity;
// Remember the index
intNearestPntr = L;
}
}
// Get the closest tree
triTree = paryTrees[intNearestPntr];
// Get the normalized tree position of the closest tree
vecTree = triTree.position;
// Get the world coordinates of the tree position
vec3 = (Vector3.Scale(pvecTerrainSize, vecTree) + pvecTerrainPosition);
// Scale the capsule having the capsule collider that represents a solid tree
pgobTreeCollide.transform.localScale = (pvecCollideScale * triTree.heightScale);
// Add some height to position the capsule correctly on the tree
vec3.y += pgobTreeCollide.transform.localScale.y;
// Position the capsule having the capsule collider at the nearest tree
pgobTreeCollide.transform.position = vec3;
}
}
That’s it.
As I mentioned before, you can put the tree collider object on its own layer, and just raycast to that layer if you have terrain tree colliders.
For example, you could modify your current script to something like this :
public LayerMask treeLayer = -1; // change this to your tree layer in the inspector
void Hit()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
Vector3 DirectionRay = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(ray, out hit, treeLayer))
{
Debug.DrawRay(transform.position, DirectionRay, Color.red);
if ( hit.collider.gameObject.name == "Tree" )
{
distance = hit.distance;
if(distance <= range)
{
GameObject.Find("ScotsPine2").SendMessage("GiveWood", SendMessageOptions.DontRequireReceiver);
}
}
}
}