Code Sample: Relative Object Placement in Unity
The Gist for the can be accessed here.
Here I will explain how I coded this step-by-step:
/**
* Params:
* childName: the name of the object that is being created(ex: vase)
* parentName: the name of the object that is being used to describe the relative destination(ex: table)
* Pre: none
* Post: prefab with name childName is created on top of the parentName.
**/
public void createOnTop(string childName, string parentName)
{
GameObject parent = GetClosest(parentName);
float height = GetObjectHeight(parent);
GameObject child = createPrefab(childName);
child.transform.position = parent.transform.position;
child.transform.localPosition = new Vector3(child.transform.position.x, height, child.transform.position.z);
// can't change only y. have to declare a new vector3
lastObject = child;
moveControls.autoSelect(child);
}
public GameObject GetClosest(string prefabName)
{
return GetClosest(prefabName, tag_levelobjects);
}
public GameObject GetClosest(string prefabName, string tagName) // Thanks to bigmisterb from unity forums.
{
GameObject[] objects = GameObject.FindGameObjectsWithTag(tagName);
GameObject closest = null;
float dot = -2.0f;
foreach (GameObject obj in objects) // if prefabName!
{
if (obj.name.ToLower() == prefabName || obj.name.ToLower() == prefabName + "(clone)" || obj.name.ToLower() == prefabName + " (1)")
{
// store the Dot compared to the camera's forward position (or where the object is locally in the camera's space)
// Very important that the point is normalized.
//Vector3 t = Camera.main.transform.position;
Vector3 localPoint = Camera.main.transform.InverseTransformPoint(obj.transform.position).normalized;
Vector3 forward = Vector3.forward;
float test = Vector3.Dot(localPoint, forward);
if (test > dot)
{
dot = test;
closest = obj;
Debug.Log("closest: " + closest.name);
}
}
else { Debug.Log(obj.name + " " + prefabName); }
}
return closest;
}
max = obj.transform.position.y + (obj.GetComponent<Renderer>().bounds.size.y / 2);
public float GetObjectSizeOn(GameObject obj, int dim)
{
float max = 0;
{
if (obj.GetComponent<Renderer>() != null)
max = obj.transform.position.y + (obj.GetComponent<Renderer>().bounds.size.y / 2); // center height + object total height/2
}
else
{
float check = 0;
foreach (Renderer renderer in obj.GetComponentsInChildren<Renderer>())
{
check = renderer.transform.position.y + (renderer.bounds.size.y / 2);
if (check > max)
max = check;
}
}
return max;
}
public GameObject createPrefab(string prefabName)
{
return createPrefab(prefabName, Vector3.zero);
}
public GameObject createPrefab(string prefabName, Vector3 position)
{
GameObject pre;
Quaternion rotation = new Quaternion(0, 0, 0, 0);
if (namedEntities.TryGetValue(prefabName, out pre)) // get game object from Entity Dictionary
{
pre = Instantiate(pre, position, pre.transform.rotation) as GameObject;
Debug.Log("add");
saver.addCreatedObject(prefabName);
lastObject = pre;
moveControls.autoSelect(pre);
return pre;
}
return null;
}