# 3. Evaluate and Placement
Part of [[Splines]]. Prev: [[2. Knots and Tangent Modes]]. Next: [[4. SplineAnimate Dollies and Cameras]].
`t` in these APIs is a **normalized** interpolation value (0 at the start, 1 at the end of the evaluated spline). It is not metres. If you need even spacing in world units, convert with spline length (see pitfalls).
## 3.1 Evaluate a point
`SplineUtility.Evaluate` (2.8/2.9 API) samples a `Spline`:
```csharp
using UnityEngine;
using UnityEngine.Splines;
public static class SplineSample
{
/// <summary>Evaluates a container's spline 0 at normalized t. NOT compiled in Unity.</summary>
public static bool TryEvaluate(SplineContainer container, float t, out Vector3 position, out Vector3 tangent, out Vector3 up)
{
position = default;
tangent = default;
up = default;
if (container == null || container.Spline == null) return false;
t = Mathf.Clamp01(t);
return SplineUtility.Evaluate(container.Spline, t, out position, out tangent, out up);
}
}
```
`SplineContainer` also exposes `Evaluate` overloads: a **combined** evaluate (when the container has a path that should be treated as a whole) and a **per-spline-index** evaluate. Read the 2.9 IntelliSense for the overload you want: some return local positions that you must `container.transform.TransformPoint`, others already account for the container transform. **Confirm the space of the overload you call before you parent objects.** Flag: this series does not pin a single overload's space from memory - check the 2.9 method remarks in your Editor.
If you use the container's `Evaluate` and the results sit at the origin, you almost certainly forgot the container transform or picked a local-space overload.
## 3.2 Place posts along a path
```csharp
using UnityEngine;
using UnityEngine.Splines;
/// <summary>
/// Instances a prefab at even *normalized* t steps. For even world spacing, see the length note below.
/// NOT compiled in Unity.
/// </summary>
public sealed class SplinePrefabsPlacer : MonoBehaviour
{
[SerializeField] SplineContainer container;
[SerializeField] GameObject prefab;
[SerializeField] int count = 8;
[SerializeField] bool lookAlongTangent = true;
[ContextMenu("Place")]
public void Place()
{
if (container == null || prefab == null || count < 1) return;
var spline = container.Spline;
if (spline == null) return;
bool closed = spline.Closed;
int steps = closed ? count : Mathf.Max(2, count);
for (int i = 0; i < (closed ? count : steps); i++)
{
float t = closed ? (i / (float)count) : (i / (float)(steps - 1));
if (!SplineUtility.Evaluate(spline, t, out var pos, out var tangent, out var up))
continue;
pos = container.transform.TransformPoint(pos);
tangent = container.transform.TransformDirection(tangent);
up = container.transform.TransformDirection(up);
var instance = Instantiate(prefab, pos, Quaternion.identity, transform);
if (lookAlongTangent && tangent.sqrMagnitude > 0.0001f)
instance.transform.rotation = Quaternion.LookRotation(tangent, up.sqrMagnitude > 0.0001f ? up : Vector3.up);
}
}
}
```
The `TransformPoint` step assumes `SplineUtility.Evaluate` on `container.Spline` is **local to the container**. If your 2.9 overload already returns world space, this will double-transform - **verify in Play Mode with the container off-origin** before you keep the conversion. That check is mandatory; it is the most common spline bug.
For **even world spacing**, get the spline length (`SplineUtility.CalculateLength` or the equivalent 2.9 method - confirm the name in the API) and sample by distance / length, not by raw `t`. Uniform `t` packs posts tighter on a sharp curve if the parameterization is not arc-length.
This is a generate-in-Editor / ContextMenu helper. Do not `Place()` every frame. If you need to regenerate, destroy previous children first in a *new* method you write carefully - this repo's safety rules for *tutorial authors* do not apply inside Unity, but a student who runs Place twice will stack prefabs. A production placer should clear or reuse instances.
## 3.3 Exercise
Move the container away from the origin, Place 8 cubes, and confirm they sit on the visible curve. If they cluster at the origin or at a double-offset, you have a space bug - fix the transform step, do not "nudge" the container back to zero and call it solved.
## Sources
- `SplineUtility` (2.8 docs; confirm 2.9): https://docs.unity3d.com/Packages/
[email protected]/api/UnityEngine.Splines.SplineUtility.html
- `SplineContainer` (2.8 docs; confirm 2.9): https://docs.unity3d.com/Packages/
[email protected]/api/UnityEngine.Splines.SplineContainer.html