I’ve written a series of scripts that randomize content in my game based on biomes assigned to a grid-like wilderness where each ‘tile’ is a scene. Everything’s going great so far, it can create the terrain objects, scatter things like trees and rocks appropriately, places them at terrain height so they’re not buried, and even rotates these objects randomly along the Y axis. But what I REALLY want it to do is also rotate them along the X and Z based on the height of the terrain at the edges of the object.
For example, if I have a fallen log. Right now, the script places it at the height of the terrain at the center of the log. But if it happens to be placed on a hill, half of the log is buried in the hill and the other half sticks out into thin air! I want it to instead lay flat along the slope of the hill.
I’m not really sure where to even start with this. I think it’ll have something to do with the Renderer.size. I believe I’ll basically need to get the angle between the four furthest points along both X and Z axis and then create a new rotation for the object based on those. But I’m still really hazy on how exactly Quaternions work, for example, and not sure where to go from here.
For reference, here is the script that I have which is creating and placing the objects right now:
using UnityEngine;
using System.Collections;
public class SpawnObjects : MonoBehaviour
{
public Terrain terrain; // add current terrain
public string[] objectToPlace; // list of objects to be placed on terrain
public string eventToPlace; // what event we're placing, if we are
public GameObject placingObject; // the individual object we're currently placing
public int numberOfObjects; // number of how many objects will be created
public int posMin; // minimum y position
public int posMax; // maximum x position
public bool posMaxIsTerrainHeight; // the maximum height is the terrain height
public bool isEvent; // determine if we're placing an object or an event
public int numberOfPlacedObjects; // number of the plaed objects
private int terrainWidth; // terrain size x axis
private int terrainLength; // terrain size z axis
private int terrainPosX; // terrain position x axis
private int terrainPosZ; // terrain position z axis
private float yDisplace; // how far to move the object above the terrain
AllObjects items;
// Create objects on the terrain with random positions
public void PlaceObject()
{
items = GetComponent<AllObjects> ();
terrainWidth = 500; // get terrain size x
terrainLength = 500; // get terrain size z
terrainPosX = 0; // get terrain position x
terrainPosZ = 0; // get terrain position z
if(posMaxIsTerrainHeight == true)
{
posMax = (int)terrain.terrainData.size.y;
}
int posx = Random.Range(terrainPosX, terrainPosX + terrainWidth); // generate random x position
int posz = Random.Range(terrainPosZ, terrainPosZ + terrainLength); // generate random z position
float posy = Terrain.activeTerrain.SampleHeight(new Vector3(posx, 0, posz)); // get the terrain height at the random position
if (isEvent) {
int r = Random.Range (0, items.items [eventToPlace].Length); // pick a random event from the list of possibles
placingObject = items.items [eventToPlace] [r]; // set prefab as event obj we're working with
if (posy <= posMax && posy >= posMin) {
yDisplace = (placingObject.GetComponent<Renderer> ().bounds.size.y) / 2; // get height of object so it doesn't spawn half-buried
Instantiate (placingObject, new Vector3 (posx, posy + yDisplace, posz), Quaternion.AngleAxis (Random.Range (0, 360), Vector3.up)); // create object
}
} else {
int r = Random.Range (0, objectToPlace.Length); // pick object type from scatterables list
int i = Random.Range (0, items.items [objectToPlace [r]].Length); // select prefab from list of items of that type
placingObject = items.items [objectToPlace [r]] [i]; // set prefab as obj we're working with
if (posy <= posMax && posy >= posMin) {
yDisplace = (placingObject.GetComponent<Renderer> ().bounds.size.y) / 2; // get height of object so it doesn't spawn half-buried
Instantiate (placingObject, new Vector3 (posx, posy + yDisplace, posz), Quaternion.AngleAxis (Random.Range (0, 360), Vector3.up)); // create object
numberOfPlacedObjects++;
}
// numberOfPlacedObjects is smaller than numberOfObjects
if (numberOfPlacedObjects < numberOfObjects) {
PlaceObject (); // place another one
}
}
}
}
If anyone can please point me in the right direction that would be awesome! Thanks!