Skip to content

Instantly share code, notes, and snippets.

@belzecue
Created June 25, 2019 14:53
Show Gist options
  • Save belzecue/fe247fbfc4f555137dd36e290e7ff5cb to your computer and use it in GitHub Desktop.
Save belzecue/fe247fbfc4f555137dd36e290e7ff5cb to your computer and use it in GitHub Desktop.
Uses this octree implementation: https://github.com/Nition/UnityOctree
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnByOctree : MonoBehaviour
{
[Header("Spawn Prefab")]
public GameObject prefab;
[Header("Octree Setup")]
public float radius = 10;
public float minNodeSize = 4;
public float looseness = 1.25f;
public Vector3 center;
public bool showGizmos;
[Header("Spawn Position")]
public AnimationCurve positionCurve;
[Header("Spawn Size")]
public AnimationCurve scaleCurve;
private Transform objTransform, rootTransform;
private BoundsOctree<GameObject> boundsTree;
private Bounds newObjBounds;
private int retries;
private float survivalChance, scale, normalScale;
private bool enableCreateFromPrefab = true;
private Vector3 spawnDir;
private new Renderer renderer;
private Fergicide.Rotater rotater;
private void Start()
{
boundsTree = new BoundsOctree<GameObject>(radius * 2f, center, minNodeSize, looseness);
rootTransform = new GameObject("CubeRoot").transform;
rotater = rootTransform.gameObject.AddComponent<Fergicide.Rotater>();
rotater.freq = 0.1f;
rotater.speed = 3;
while (enableCreateFromPrefab) CreateFromPrefab();
}
public void CreateFromPrefab()
{
if (enableCreateFromPrefab)
{
if (retries > 200)
{
enableCreateFromPrefab = false;
boundsTree = null;
return;
}
}
else return;
spawnDir = Vector3.zero + Random.insideUnitSphere * radius * Random.value;
normalScale = spawnDir.magnitude / radius;
if (Random.value > positionCurve.Evaluate(normalScale))
{
retries++;
CreateFromPrefab();
return;
}
GameObject obj = Instantiate(prefab);
objTransform = obj.transform;
objTransform.localPosition = spawnDir;
objTransform.localRotation = Random.rotationUniform;
renderer = obj.GetComponent<Renderer>();
scale = (0.5f + Random.value * 1.5f);
if (Random.value > scaleCurve.Evaluate(normalScale))
{
objTransform.localScale = scale * Vector3.one;
}
newObjBounds = renderer.bounds;
if (!boundsTree.IsColliding(newObjBounds))
{
boundsTree.Add(obj, newObjBounds);
retries = 0;
obj.AddComponent<PerRenderedData>();
objTransform.parent = rootTransform;
}
else
{
retries++;
Destroy(obj);
CreateFromPrefab();
}
}
void OnDrawGizmos()
{
if (enableCreateFromPrefab && Application.isPlaying && showGizmos)
{
boundsTree.DrawAllBounds(); // Draw node boundaries
boundsTree.DrawAllObjects(); // Draw object boundaries
// boundsTree.DrawCollisionChecks(); // Draw the last *numCollisionsToSave* collision check boundaries
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment