Mass Place Trees tagging

Hello :stuck_out_tongue: So … i used mass place trees with 4 prefabs, they are tagges as “Trees” but, when i use this script to check tags:

RaycastHit hit;
		Vector3 DirectionRay = transform.TransformDirection(Vector3.forward);
		if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
		{
			Debug.DrawRay(transform.position, DirectionRay, Color.red);
			Debug.Log( "ray hit (tag) : " + hit.collider.gameObject.tag + " : " );
			if(hit.collider.gameObject.tag == "Trees")
			{
				distance = hit.distance;
				if(distance <= range)
				{
					Debug.Log("12323123 !");
				}
			}
		}

i have in console “Untagged” but when i place manually trees (same prefabs) everything is okay and in console tag “Trees”

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);
			}
		}
	}
}

Okay guys, i found solution :slight_smile:
So … if u placing trees by mass trees option and u want to do something after hit tree (in my case it’s raycast) u can use option “mass trees” but u must place one tree on the terrain manually.
I have this:
all my trees prefabs have script called “WoodResource”:

using UnityEngine;
using System.Collections;

public class WoodResource : MonoBehaviour {

	public int wood;

	void Start ()
	{

	}

	void Update ()
	{
		
	}

	void GiveWood()
	{
		Debug.Log("Work ! :)");
	}
}

my player have “Melee” script:

public class Melee : MonoBehaviour {

	public WoodResource woodGet;

	public float attackTimer;
	public float coolDown;
	public float range;

	public float distance;

	void Start ()
	{
		attackTimer = 0;
		coolDown = 1.0f;
	}

	void Update ()
	{
		if(attackTimer > 0)
			attackTimer -= Time.deltaTime;

		if(attackTimer < 0)
			attackTimer = 0;

		if(Input.GetMouseButtonUp(0))
		{
			if(attackTimer == 0)
			{
				Hit();
				attackTimer = coolDown;
			}
		}
	}

	void Hit()
	{
		Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
		RaycastHit hit;

		Vector3 DirectionRay = transform.TransformDirection(Vector3.forward);
		if(Physics.Raycast(ray, out hit))
		{
			Debug.DrawRay(transform.position, DirectionRay, Color.red);
			distance = hit.distance;
			if(distance <= range)
			{
				GameObject.Find("ScotsPine2").SendMessage("GiveWood", SendMessageOptions.DontRequireReceiver);
			}
		}
	}
}

And my MANUALLY PLACED TREE name is “ScotsPine2”. So now, when u hit tree u send massage to script WoodResource and u can do whatever u want ;D
I hope that you understood XD

Necro, but unfortunately if you’re looking for a solution to the problem where Preserve Tree Prototype Layers, you won’t. It’s been broken and there’s no hope to fix it. You’ll need to create procedural terrain as a mesh, learn how to add trees and other details via code, paint them as Static, use frustum culling and distance-based occlusion, a good set of LoDs, and pray for the best…afaik.