ProfilerMarkers
Profiler markers in one line, with no fields or names to keep up by hand.
Quick start
| Before — Unity API | After — FastTools |
|---|---|
| |
Marker()
The marker name is built from the type, the method and the call's line number:
Where this.Marker() is called | Marker name |
|---|---|
void Step() | FlockSimulation.Step (line) |
FlockSimulation() | FlockSimulation.Ctor (line) |
float Speed { get; } | FlockSimulation.Speed (line) |
Agent this[int i] { get; } | FlockSimulation.Indexer (line) |
event Action Changed | FlockSimulation.Changed (line) |
class FlockSimulation.Agent { void Move() } | Agent.Move (line) |
class Worker<T> { void Run() } | Worker<Int32>.Run (line)Worker<Single>.Run (line) |
struct Job<T> { void Execute() } | Job<T>.Execute (line) for any T |
void Run<T>() | FlockSimulation.Run (line) for any T |
WithName()
.WithName("Steering") replaces the method in the marker name with its own text: FlockSimulation.Step (5) → FlockSimulation.Steering (5).
public void Step()
{
using var _ = this.Marker();
using (this.Marker().WithName("Steering"))
{
foreach (var agent in _agents)
{
using (this.Marker().WithName("Steering.Agent"))
ComputeSteering(agent);
}
}
using (this.Marker().WithName("Integrate"))
Integrate();
}
note
Only a string literal works: the generator reads the name from the source. With a variable, const, nameof or $"Agent {index}" the method name stays, and the argument is still evaluated on every call.
In the Profiler
The generator creates one static field per call site, so measuring allocates nothing.
HierarchyFrame 1284
FlockSimulation.Step (3)10 B0.01
Limitations
- The line number in the name changes when the call moves: compare captures from before and after an edit by the name without it.
- Calls without a marker — on an object of another type (
other.Marker()), in a static class, in aprivateorprotectednested type: analyzerAFT0010warns about it. - A discarded scope.
this.Marker();withoutusingbegins a sample that never ends — analyzerAFT0011warns about it.
warning
Measurements land in someone else's Profiler row when:
this.Marker()calls in differentpartialfiles of one type sit on the same line — they share the first one's marker;- a call without a marker sits on the same line as a marked call in the type it binds to: for
other.Marker()that is the type ofotherif it is declared in the caller's namespace or an enclosing one, for a call in a nested type — the base type unless it is in the global namespace.
Package sample
The markers from WithName() run in the ProfilerMarkers scene.

