Search Unity

Issues with tree scale and rotation in terrain tool

Discussion in 'World Building' started by ElAlesito, Jun 6, 2021.

  1. ElAlesito

    ElAlesito

    Joined:
    Mar 6, 2020
    Posts:
    6
    I am having issues with the scale and rotation of the trees while using the terrain tool to place them, my issues are:

    There is a scale mismatch between the models placed straight into the editor viewport and the ones painted by the terrain tool, the result is the painted ones looking tiny. A workaround I have tried is unticking convert units and leaving the scale factor to one (see image below)
    The problem with this solution is now if I drop a regular tree from the project window into the scene the scale is gigantic. This mismatch is really problematic to my workflow.

    Secondly, the rotation of the models is wrong.(I know this is the intended behavior when importing models) This is normally not a problem, unity usually corrects it by adding a -90 degrees rotation when you import the asset. My issue is that when I drag it from the project window it has the intended -90 degrees rotation

    But when I place the tree via the terrain tool it's sideways.

    Again I tried playing with the model settings and ticked "Bake Axis Conversion" to see if the results changed. When I did, the tree came out 180 degrees rotated

    The result is the tree in the terrain tool comes out sideways but the other way around.

    I have tried both the old and new terrain systems and the results are identical.
    How do I go about fixing this?

    PD: The models are from a free bundle by Quaternius, I imported them into the project as fbx files.
     
  2. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    In the 2nd image you can see the green arrow (Y axis) isn't vertical / pointing up. 90 degrees around Z should fix it - either via export/import settings or vertex data.
     
  3. ElAlesito

    ElAlesito

    Joined:
    Mar 6, 2020
    Posts:
    6
    As I said in the post earlier, I am aware that I could rotate them all 90 degrees in a 3d software and re export the 100 different models back into unity. But I see no option to rotate said models within unity. And I also pointed out that unity auto rotates the models when hand placing them yet it doesn't do that when using the terrain tool
    Is there a solution that doesn't involve wasting an afternoon rotating and exporting models in blender or other 3d software?

    My other question still stands, Is there a solution to the problem of differing scales with the terrain tool?
     
  4. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    I just did this for you quickly.. back up your mesh beforehand to avoid your original getting modified.

    Add these scripts to your project:
    project.jpg

    MeshRotator.cs
    Code (CSharp):
    1. using UnityEngine;
    2. public class MeshRotator : MonoBehaviour
    3. {
    4.   public MeshFilter meshFilter;
    5.   public void ApplyRotationToVertices()
    6.   {
    7.     Mesh mesh = meshFilter.sharedMesh;
    8.     Vector3[] vertices = mesh.vertices;
    9.     for (int v = 0; v < vertices.Length; v++) vertices[v] = meshFilter.transform.TransformPoint(vertices[v]);
    10.     meshFilter.transform.rotation = Quaternion.identity;
    11.     for (int v = 0; v < vertices.Length; v++) vertices[v] = meshFilter.transform.InverseTransformPoint(vertices[v]);
    12.     meshFilter.sharedMesh.vertices = vertices;
    13.     meshFilter.sharedMesh.RecalculateBounds();
    14.   }
    15. }
    Editor/MeshRotatorInspector.cs
    Code (CSharp):
    1.  
    2. using UnityEditor;
    3. using UnityEngine;
    4.  
    5. [CustomEditor(typeof(MeshRotator), true, isFallback = true)]
    6. public class MeshRotatorInspector : Editor
    7. {
    8.   private string exportTo = "Assets/rotatedMesh";
    9.   public override void OnInspectorGUI()
    10.   {
    11.     if (target.GetType() == typeof(MeshRotator))
    12.     {
    13.       MeshRotator mr = (MeshRotator)target;
    14.       if (GUILayout.Button("Apply Rotation To Vertices")) mr.ApplyRotationToVertices();
    15.       GUILayout.BeginHorizontal();
    16.       exportTo = GUILayout.TextField(exportTo);
    17.       if (GUILayout.Button("Export Mesh"))
    18.       {
    19.         string path = exportTo + ".asset";
    20.         Mesh mesh = AssetDatabase.LoadAssetAtPath<Mesh>(path);
    21.         if (mesh != null)
    22.         {
    23.           Debug.Log("file already exists");
    24.           return;
    25.         }
    26.         mesh = Instantiate<Mesh>(mr.meshFilter.sharedMesh);
    27.         AssetDatabase.CreateAsset(mesh, exportTo + ".asset");
    28.         mr.meshFilter.sharedMesh = mesh;
    29.         EditorGUIUtility.PingObject(mr.meshFilter.sharedMesh);
    30.         EditorUtility.SetDirty(mr.meshFilter);
    31.       }
    32.       GUILayout.EndHorizontal();
    33.     }
    34.     base.OnInspectorGUI();
    35.   }
    36. }
    Then create an empty GameObject, add the component.
    Then add a child GameObject to it with your Mesh in a MeshFilter (and add a MeshRenderer to that so you can see it in the scene).
    hierarchy.jpg

    Rotate the child with the mesh to however you want the vertices to be.
    Drag the child to the Mesh Filter slot on the MeshRotator.
    Click "Apply Rotation To Vertices".
    the_component.jpg

    This will apply the rotation of the child to the vertices and set the rotation of the object back to 0,0,0.

    Click "Export Mesh" to save the rotated mesh to the indicated path. You could easily extend this with scaling if you wanted to scale vertices to the object's scale in a similar way.

    Edit: All you have to do for this to work for everything (not just rotation but also for scaling mesh vertices or offsetting the origin), to "transfer" that from the Transform to the vertices, where it says
    meshFilter.transform.rotation = Quaternion.identity;
    , replace that with this:
    Code (CSharp):
    1.     meshFilter.transform.localRotation = Quaternion.identity;
    2.     meshFilter.transform.localScale = Vector3.one;
    3.     meshFilter.transform.localPosition = Vector3.zero;
    It's not everything you're after and it's just quick for illustration, but hopefully the above helps you work out an automated solution.
     
    Last edited: Jun 7, 2021
  5. ElAlesito

    ElAlesito

    Joined:
    Mar 6, 2020
    Posts:
    6
    Thank you very much for your help, I implemented it and it certainly works.

    Sadly there doesn't seem to be a way to have the same scale of trees in the terrain tool and the project without keeping a duplicate. I don´t understand why the terrain tool chooses to make the trees minuscule.
     
    adamgolden likes this.
  6. adamgolden

    adamgolden

    Joined:
    Jun 17, 2019
    Posts:
    1,555
    I'm not well-versed with the Terrain system - but unless I'm mistaken the general rule of thumb with scale is that 1 unit = 1m. There are technical reasons why this is the case.. for example you can't go more than a couple thousand units from the origin without also writing or integrating a floating origin solution (i.e. to prevent things that are close to each other from z-fighting due to precision loss, among other issues that arise).

    A tree that's 10 units tall is actually pretty big (almost 33 feet), but other aspects of the scene can throw this off visually. For example, surface complexity / granularity or texturing or uv scale, or relative scale of other objects nearby like if you have a rock that's 10x10x10, you might look at the rock and for some reason it looks like the size of a mini-fridge when in fact you could have a campsite on top of it. Anyway just some thoughts, I don't know the specifics of your project of whether any of this applies.
     
  7. Jelmer123

    Jelmer123

    Joined:
    Feb 11, 2019
    Posts:
    243
    This is pretty annoying. Can't fix it on import in Unity, can't fix it in a prefab in Unity, can't make it a child of another gameObject in Unity, because then Terrain complains that the mesh renderer is missing. Very flexible, as usual.