Most recent UPDATE 20180412:
I saw this post today and I have found a solution some weeks ago. (which I want to share today)
Our (internal) solution is based on the Unity video tutorial with Tips and Tricks https://unity3d.com/es/learn/tutorials/topics/tips/unity-tips-tricks-3 and heavily modified for MegAgeM needs. However the code shown from the video works 99% fine and is my recommendation for you, if you have to align a lot of GameObjects with the ground.
using UnityEngine; using UnityEditor; using System.Collections; public class AlignWithGround : MonoBehaviour { [MenuItem("Tools/Transform Tools/Align with ground %t")] static void AlignWithGround2() { Transform[] transforms = Selection.transforms; foreach (Transform myTransform in transforms) { RaycastHit hit; if (Physics.Raycast(myTransform.position, -Vector3.up, out hit)) { Vector3 targetPosition = hit.point; if (myTransform.gameObject.GetComponent<MeshFilter>() != null) { Bounds bounds = myTransform.gameObject.GetComponent<MeshFilter>().sharedMesh.bounds; targetPosition.y += bounds.extents.y; } myTransform.position = targetPosition; Vector3 targetRotation = new Vector3(hit.normal.x, myTransform.eulerAngles.y, hit.normal.z); myTransform.eulerAngles = targetRotation; } } } }
Original Post:
We had this issue during the GlobalGameJam and I’m pretty sure that I was once able to do this directly in the editor. However I forgot the solution and have no glue anymore and so I decided to do a quick research on “how to place the flying GameObjects on the terrain or plane or ground” (See Screenshots to understand my problem here – some trees are just a few meters up the terrain).
First I stumbled over an answer where someone recommends during runtime a “raycast” to what is the “ground” or “floor” in the scene.
I guess this might be a solution… But…
I also found this thread, where someone has created a JS script for usage in the Unity Editor to place the objects on the ground.
Some years later someone created a C# solution and… Someone pointed out a hotkey which seems liek the knowledge I once had and lost (see beginning of this post)
https://forum.unity.com/threads/here-is-an-editor-script-to-help-place-objects-on-ground.38186/
I will test the code in the next days and add some updates on how this worked.
Update 1:
Tested… Seems to work – but not for our scene. (Our tree models are prefabs combinated from different Objects – all of them will be checked – but this results in bad results – since the tree trunk is bellow the normal tree green and both are placed to the ground)
//source https://forum.unity.com/threads/here-is-an-editor-script-to-help-place-objects-on-ground.38186/ using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine; using UnityEditor; public class DropObjectsEditorWindow : EditorWindow { private bool m_bAlignRotations = true; // Add a menu item [MenuItem("Window/Drop Object(s)")] static void Awake() { // Get or create an editor window EditorWindow.GetWindow<DropObjectsEditorWindow>().Show(); } void OnGUI() { EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Drop/align selected object(s)")) { DropObjects(); } EditorGUILayout.EndHorizontal(); // Add checkbox for rotation alignment m_bAlignRotations = EditorGUILayout.ToggleLeft("Align Rotations", m_bAlignRotations); } void DropObjects() { Undo.RecordObjects(Selection.transforms, "Drop Objects"); for (int i = 0; i < Selection.transforms.Length; i++) { GameObject go = Selection.transforms[i].gameObject; if (!go) continue; // Cast a ray and get all hits RaycastHit[] rgHits = Physics.RaycastAll(go.transform.position, -go.transform.up, Mathf.Infinity); // We can assume we did not hit the current game object, since a ray cast from within the collider will implicitly ignore that collision int iBestHit = -1; float flDistanceToClosestCollider = Mathf.Infinity; for (int iHit = 0; iHit < rgHits.Length; ++iHit) { RaycastHit CurHit = rgHits[iHit]; // Assume we want the closest hit if (CurHit.distance > flDistanceToClosestCollider) continue; // Cache off the best hit iBestHit = iHit; flDistanceToClosestCollider = CurHit.distance; } // Did we find something? if (iBestHit < 0) { Debug.LogWarning("Failed to find an object on which to place the game object " + go.name + "."); continue; } // Grab the best hit RaycastHit BestHit = rgHits[iBestHit]; // Set position go.transform.position = new Vector3(BestHit.point.x, BestHit.point.y, BestHit.point.z); // Set rotation if (m_bAlignRotations) { go.transform.rotation *= Quaternion.FromToRotation(go.transform.up, BestHit.normal); } } } }
Update 2:
This is a free asset pack with a model grounder in it. It’s untested, but the name sounds promissing to provide a solution for the grounding of the trees.
https://www.assetstore.unity3d.com/en/?stay#!/content/108464
However… In the Scene View it is possible to navigate through the world with WASD if the right mouse button is pressed. This is how I fixed now some of the flying trees.