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

Instantiate SpeedTree colliders at runtime via script

Discussion in 'Scripting' started by Hikiko66, Sep 21, 2016.

  1. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,300
    So I had a system for doing this for unity trees, and it seemed to work fine.
    Speed trees are different though.

    They have per instance rotation, and they usually also have multiple colliders.

    I need to manage these colliders, so I can't instance them automatically via terrain options, I need to instance them via script.

    The problem I am having is orienting the colliders to match the particular tree instance.
    So, the colliders positions, rotations and scales.

    This is as close as I have gotten, but my maths is pretty terrible. I've been relying on google.

    The TreeBox is positioned correctly. The colliders and their parent objects are not correctly placed most of the time.

    Code (csharp):
    1.  
    2.                 //Instantiate tree box at the position of the Tree
    3.                 GameObject TreeBox = (GameObject)GameObject.Instantiate(TreeColliderParentObject, Vector3.Scale(TerrainTrees[x][y].position, Terrains[x].terrainData.size) + Terrains[x].transform.position, Quaternion.identity);
    4.                 TreeBox.transform.parent = Terrains[x].transform;
    5.  
    6.                 //Add to array of Trees
    7.                 TerrainTreeBoxes[x][y] = TreeBox;
    8.                 //Fetch this Tree prototype
    9.                 var treePrefab = Terrains[x].terrainData.treePrototypes[TerrainTrees[x][y].prototypeIndex].prefab;
    10.  
    11.                 //Fetch the capsule colliders for this Tree
    12.                 CapsuleCollider[] TreeCollider = (CapsuleCollider[])treePrefab.GetComponentsInChildren<CapsuleCollider>();
    13.                 //
    14.  
    15.                 //Loop through the colliders for this tree
    16.                 for (int z = 0; z < TreeCollider.Length; z++)
    17.                 {
    18.                     //Instantiate an object that will act as parent object of this collider component
    19.                     GameObject TreeColObj = (GameObject)GameObject.Instantiate(TreeColliderParentObject, TreeBox.transform.position, Quaternion.identity);
    20.                     //Assign Treebox as the parent of this collider holding object
    21.                     TreeColObj.transform.parent = TreeBox.transform;
    22.  
    23.                     //Add capsule collider component to the parent object
    24.                     CapsuleCollider TreeCapsule = (CapsuleCollider)TreeColObj.AddComponent<CapsuleCollider>();
    25.  
    26.                     //Sync the TreeColObject pos/rot/sca to that of the transform of the prefab
    27.                     TreeColObj.transform.localRotation = TreeCollider[z].transform.rotation;
    28.                     TreeColObj.transform.localPosition = TreeCollider [z].transform.position;
    29.                     TreeColObj.transform.localScale = Vector3.one * TerrainTrees [x] [y].widthScale;
    30.  
    31.                     //Sync the collider attributes
    32.                     TreeCapsule.direction = TreeCollider[z].direction;
    33.                     TreeCapsule.radius = TreeCollider[z].radius;
    34.                     TreeCapsule.height = TreeCollider[z].height;
    35.                     TreeCapsule.center = TreeCollider[z].center;
    36.                     TreeCapsule.enabled = false;
    37.                 }
    38.  
    39.                 //Scale and rotate our new parent Tree object to match that of the terrain tree.
    40.                 TreeBox.transform.localScale = new Vector3 (TerrainTrees [x] [y].widthScale, TerrainTrees [x] [y].heightScale, TerrainTrees [x] [y].widthScale);
    41.                 TreeBox.transform.rotation = Quaternion.AngleAxis(TerrainTrees [x] [y].rotation * Mathf.Rad2Deg, Vector3.up);
    42.  
    Any help is appreciated
     
    Last edited: Sep 21, 2016
  2. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    You have some weird stuff going on, but if I understand correctly, you are setting the TreeColObj local rotation to the TreeCollider's global rotation, which is a component of TreeColObj. So, in essence, you are setting the local rotation value of TreeColObj to it's global rotation value. If both the TreeBox and the TreeColObj have a global rotation value of (0, 15, 0) then TreeColObj's local rotation will actually be 0. But what you've done is you've now set the local rotation to (0, 15, 0), making it offset from the parent.
    So, to summarize: TreeBox global rotation: (0, 15, 0)
    TreeColObj global rotation upon instantiation: (0, 15, 0) *I'l be honest, I'm not sure what value you get from Quaternion.Identity
    TreeColObj local rotation before line 17: (0, 0, 0) *This is aligned with the parent
    TreeColObj local rotation after line 27: (0, 15, 0)

    What I want to know is, based on my own experience with SpeedTree, why aren't you creating a prefab with all the colliders you want attached, etc, and instantiating that prefab?

    EDIT: After doing some more looking up on what Quaternion.Identity does, I think it would make more sense to have line 27 be
    Code (csharp):
    1. TreeColObj.transform.localRotation = Quaternion.Identity
     
  3. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,300
    changing that line turns the colliders horizontal.

    It's possibly a maths problem, or it could be a logic problem. Maybe I'm scaling/positioning/rotating the parents and children in the wrong order? I dunno.

    I need to instantiate the colliders via script because last time I checked, when you generate them via terrain settings and interact with them, the "hit" comes back as saying you hit terrain.
    I need my AI to be able to figure out where the trees and colliders are.
     
    Last edited: Sep 22, 2016
  4. Vedrit

    Vedrit

    Joined:
    Feb 8, 2013
    Posts:
    514
    If you're making the local rotation 0 and it aligns into an odd direction, sounds like the scaling is off.

    I believe that is the case if you are indeed using the terrain to spawn the trees, but if you are using SpeedTree trees, you can spawn them as regular gameObjects and they'll still behave like terrain trees, which means you can create prefabs with all the components, children and tags you want.