123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using UnityEngine;
- namespace SplineMesh {
- /// <summary>
- /// Example of component to places assets along a spline. This component can be used as-is but will most likely be a base for your own component.
- ///
- /// In this example, the user gives the prefab to place, a spacing value between two placements, the prefab scale and an horizontal offset to the spline.
- /// These three last values have an additional range, allowing to add some randomness. for each placement, the computed value will be between value and value+range.
- ///
- /// Prefabs are placed from the start of the spline at computed spacing, unitl there is no lentgh remaining. Prefabs are stored, destroyed
- /// and built again each time the spline or one of its curves change.
- ///
- /// A random seed is used to obtain the same random numbers at each update. The user can specify the seed to test some other random number set.
- ///
- /// Place prefab along a spline and deform it easily have a lot of usages if you have some imagination :
- /// - place trees along a road
- /// - create a rocky bridge
- /// - create a footstep track with decals
- /// - create a path of firefly in the dark
- /// - create a natural wall with overlapping rocks
- /// - etc.
- /// </summary>
- [ExecuteInEditMode]
- [SelectionBase]
- [DisallowMultipleComponent]
- public class ExampleSower : MonoBehaviour {
- private GameObject generated;
- private Spline spline = null;
- private bool toUpdate = true;
- public GameObject prefab = null;
- public float scale = 1, scaleRange = 0;
- public float spacing = 1, spacingRange = 0;
- public float offset = 0, offsetRange = 0;
- public bool isRandomYaw = false;
- public int randomSeed = 0;
- private void OnEnable() {
- string generatedName = "generated by "+GetType().Name;
- var generatedTranform = transform.Find(generatedName);
- generated = generatedTranform != null ? generatedTranform.gameObject : UOUtility.Create(generatedName, gameObject);
- spline = GetComponentInParent<Spline>();
- spline.NodeListChanged += (s, e) => {
- toUpdate = true;
- foreach (CubicBezierCurve curve in spline.GetCurves()) {
- curve.Changed.AddListener(() => toUpdate = true);
- }
- };
- foreach (CubicBezierCurve curve in spline.GetCurves()) {
- curve.Changed.AddListener(() => toUpdate = true);
- }
- }
- private void OnValidate() {
- toUpdate = true;
- }
- private void Update() {
- if (toUpdate) {
- Sow();
- toUpdate = false;
- }
- }
- public void Sow() {
- UOUtility.DestroyChildren(generated);
- UnityEngine.Random.InitState(randomSeed);
- if (spacing + spacingRange <= 0 ||
- prefab == null)
- return;
- float distance = 0;
- while (distance <= spline.Length) {
- CurveSample sample = spline.GetSampleAtDistance(distance);
- GameObject go;
- go = Instantiate(prefab, generated.transform);
- go.transform.localRotation = Quaternion.identity;
- go.transform.localPosition = Vector3.zero;
- go.transform.localScale = Vector3.one;
- // move along spline, according to spacing + random
- go.transform.localPosition = sample.location;
- // apply scale + random
- float rangedScale = scale + UnityEngine.Random.Range(0, scaleRange);
- go.transform.localScale = new Vector3(rangedScale, rangedScale, rangedScale);
- // rotate with random yaw
- if (isRandomYaw) {
- go.transform.Rotate(0, 0, UnityEngine.Random.Range(-180, 180));
- } else {
- go.transform.rotation = sample.Rotation;
- }
- // move orthogonaly to the spline, according to offset + random
- var binormal = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.right).normalized;
- var localOffset = offset + UnityEngine.Random.Range(0, offsetRange * Math.Sign(offset));
- localOffset *= sample.scale.x;
- binormal *= localOffset;
- go.transform.position += binormal;
- distance += spacing + UnityEngine.Random.Range(0, spacingRange);
- }
- }
- }
- }
|