Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Spawn Objects of differing lengths uniformly along a Spline
#1
I need to figure out how to spawn objects (in this case vehicles) that are of different lengths with uniform spacing along a spline (in this case representing a road). I'm having a lot of trouble getting this to work correctly though, it seems like the longer objects always throw off everything else down the line and I wind up with results that are just completely not correct. 

I figured out how to get objects spawning MOSTLY uniformly using this approach...

Code:
[ContextMenu("Spawn Vehicles")]
       private void EditorSpawn()
       {
           int startIndex = 0;

           int size = spline.ControlPointsList.Count - startIndex;
           float[] distances = new float[size]; // node distances
           Vector3 lastPosition = spline.ControlPointsList[0].transform.position;

           //populate the node distances
           float distance = 0;
           for (int i = 0; i < size; i++)
           {
               int index = i + startIndex;
               Vector3 nodePosition = spline.ControlPointsList[index].transform.position; // define the vertices based on the nodes:
               distance += (nodePosition - lastPosition).magnitude;
               distances[i] = distance; // distance along the path
               lastPosition = nodePosition;
           }

           // find the desired distance between objects:
           float spacing = distance / (SpawnCount - 1); // initialize conditions to create 1st object
           lastPosition = spline.ControlPointsList[startIndex].position;
           int curNode = startIndex;
           float objectDistance = 0f;
           float lastDistance = 0f;

           for (int i = 0; i < SpawnCount; i++)
           {
               // find direction and position of current segment:
               Vector3 dir = (spline.ControlPointsList[curNode].position - lastPosition).normalized;
               Vector3 pos = lastPosition + dir * (objectDistance - lastDistance);

               //spawn and initialize vehicle
               CurvyVehicle vehicle = (CurvyVehicle)UnityEditor.PrefabUtility.InstantiatePrefab(GetPrefab());
               vehicle.transform.SetParent(ParentTransform);
               vehicle.Controller.Spline = spline;
               vehicle.Controller.InitialPosition = spline.GetNearestPointTF(pos);
               vehicle.Speed = vehicleSpeed;

               objectDistance += spacing;

               // find next object distance
               // find segment where to put next object:
               while (objectDistance > distances[curNode] && curNode < size - 1)
               {
                   lastPosition = spline.ControlPointsList[curNode].position;
                   lastDistance = distances[curNode];
                   curNode++;
               }
           }
       }

but since it doesnt take into account the length of the objects being spawned it can lead to serious issues with cars spawning inside a sufficiently long car in from of them. My efforts to incorporate vehicle length have pretty much failed, and I'm open to any suggestions on how to get this actually working correctly. here is how that is looking right now.

Code:
       [ContextMenu("Spawn Vehicles Alt")]
       private void EditorSpawnAlt()
       {
           int startIndex = 0;

           int size = spline.ControlPointsList.Count - startIndex;
           float[] distances = new float[size]; // node distances
           Vector3 lastPosition = spline.ControlPointsList[0].transform.position;

           //populate the node distances
           float distance = 0;
           for (int i = 0; i < size; i++)
           {
               int index = i + startIndex;
               Vector3 nodePosition = spline.ControlPointsList[index].transform.position; // define the vertices based on the nodes:
               distance += (nodePosition - lastPosition).magnitude;
               distances[i] = distance; // distance along the path
               lastPosition = nodePosition;
           }

           //need to populate vehicles so we know lengths ahead of time!
           CurvyVehicle[] spawnedVehicles = new CurvyVehicle[spawnCount];
           float totalVehicleLength = 0f;
           for (int i = 0; i < spawnCount; i++)
           {
               CurvyVehicle vehicle = (CurvyVehicle)UnityEditor.PrefabUtility.InstantiatePrefab(GetPrefab());
               vehicle.transform.SetParent(ParentTransform);
               vehicle.Controller.Spline = spline;
               vehicle.Speed = vehicleSpeed;
               totalVehicleLength += vehicle.VehicleLength;

               spawnedVehicles[i] = vehicle;
           }

           // find the desired distance between objects:
           lastPosition = spline.ControlPointsList[startIndex].position;
           int curNode = startIndex;
           float objectDistance = 0f;
           float lastDistance = 0f;
           float spacing = 0f;
           float offset = ((distance - totalVehicleLength) / (SpawnCount - 1));

           //now we need to iterate through the vehicles now that we know all the lengths
           for (int i = 0; i < spawnedVehicles.Length; i++)
           {
               // find direction and position of current segment:
               spacing = offset + spawnedVehicles[i].VehicleLength;

               Vector3 dir = (spline.ControlPointsList[curNode].position - lastPosition).normalized;
               Vector3 pos = lastPosition + dir * (objectDistance - lastDistance);

               //spawn and initialize vehicle
               spawnedVehicles[i].Controller.InitialPosition = spline.GetNearestPointTF(pos);

               objectDistance += spacing;

               // find next object distance
               // find segment where to put next object:
               while (objectDistance > distances[curNode] && curNode < size - 1)
               {
                   lastPosition = spline.ControlPointsList[curNode].position;
                   lastDistance = distances[curNode];
                   curNode++;
               }
           }

       }
Reply
#2
Hi,
Here is how I would have coded it:
(the following is pseudo code, but should be clear enough so you can easily implement the real thing)
Code:
float splineLength = yourSpline.Length;
float vehiculesLength = //the sum of all your vehicules' length;
float totalSpaceBetweenVehicules = splineLength - vehiculesLength;
Assert.IsTrue(totalSpaceBetweenVehicules  > 0); // don't forget to handle the case where this is not true
float perVehiculeSpacing = totalSpaceBetweenVehicules / (vehiculesCount - 1);
float currentDistance = 0;
foreach (var vehicule in vehicules)
{
   vehicule.CurvyController.AbsolutePosition = currentDistance;
   currentDistance += (vehicule.VehiculeLength + perVehiculeSpacing);
}
Note that I used AbsolutePosition instead of InitialPosition, because InitialPosition is deprecated in the latest Curvy version. If you want to stick to old Curvy versions, then you can use InitialPosition while setting Position mode to Absolute.
I hope this helps
Please consider leaving a review for Curvy. This will help a lot keeping Curvy relevant in the eyes of the Asset Store algorithm.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Curvy Line Renderer for UI Spline? gekido 1 1 1 hour ago
Last Post: _Aka_
  Get position of all control points for a spline gekido 1 2 1 hour ago
Last Post: _Aka_
Bug Changing spline connection in inspector causes splines to revert to defaults lacota 3 6 03-18-2024, 07:55 PM
Last Post: _Aka_
  GO can't fit end of the spline GameDeveloperek4123 3 13 03-04-2024, 11:06 AM
Last Post: _Aka_

Forum Jump: