2
\$\begingroup\$

I have been working on an old DOS-styled game, and I began work on the trees for my terrain. Here is a group of them:

They, right now, are simply objects in the scene. This works, but is very cumbersome when mass placing them. I want to have them part of the terrain. I tried simply adding them as a detail mesh, but they didn't retain scripts nor colliders. Is there a way to accomplish this?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

There’s no way to do it directly because they are no longer GameObjects for performance reasons. However, if you add them as tree objects on the terrain, you can write a script that runs on awake which gets the position of the trees and replaces them all programmatically with an instantiated prefab. Use Terrain.terrainData.treeInstances for this purpose:

(Note: This is untested)

using UnityEngine;

[RequireComponent(typeof(Terrain))]
public class TreeSwapper : MonoBehaviour
{
    //Fill this in the inspector with the prefabs to use in place of the tree prototypes defined in the Terrain object.
    public GameObject[] TreePrototypes;

    void Awake()
    {
        var data = GetComponent<Terrain>().terrainData;

        foreach (var instance in data.treeInstances) {
            var tree = Instantiate(TreePrototypes[instance.prototypeIndex], instance.position, Quaternion.euler(0,Mathf.Rad2Deg * instance.rotation,0), transform);
            tree.transform.localScale = new Vector3(instance.widthScale, instance.heightScale, instance.widthScale);
        }
        data.treeInstances = new TreeInstance[0];
    }
}

Note to anybody using this: Terrain does what it does for a very good reason: performance. Don’t expect to be able to put down a ton of trees, run this script, and expect continued good performance.

For that matter, having a script on every tree is a very uncommon use case. You may want to re-examine what you’re doing. Does each tree really need to be doing its own thing?

\$\endgroup\$
9
  • \$\begingroup\$ Would you happen to have a script that does this? \$\endgroup\$ Commented Jan 24, 2018 at 1:54
  • \$\begingroup\$ Sample added. See above. It's currently untested though, and there are some optimizations to be made. \$\endgroup\$
    – Ed Marty
    Commented Jan 24, 2018 at 1:59
  • \$\begingroup\$ Ok, got the position stuff figured out, but the Quaternion.euler still isn't working right. \$\endgroup\$ Commented Jan 24, 2018 at 2:31
  • \$\begingroup\$ What's happening? Depending on your needs, simply using Quaternion.identity may be sufficient. \$\endgroup\$
    – Ed Marty
    Commented Jan 24, 2018 at 2:42
  • \$\begingroup\$ I fixed that and a few more issues (going to edit code once this last issue is solved). Here is my current line 11: GameObject tree = Instantiate(TreePrototypes[instance.prototypeIndex], transform.position, transform.rotation); it tells me: Cannot implicitly convert type 'UnityEngine.Object' to 'UnityEngine.GameObject'. An explicit conversation exists (are you missing a cast?) do you know how to fix this issue? \$\endgroup\$ Commented Jan 24, 2018 at 2:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .