Appearance
Runtime API
This page covers the three classes you interact with at runtime: PPGComponent (the MonoBehaviour), PPGGraphAsset (the asset), and PPGGraphExecutor (the internal engine).
PPGComponent
PPGComponent is the MonoBehaviour that owns the generation lifecycle on a GameObject. Attach it to any GameObject, assign a PPGGraphAsset, and call Generate().
csharp
using IsuzuWorks.PPG;
using UnityEngine;
public sealed class PlacementTrigger : MonoBehaviour
{
[SerializeField] private PPGComponent placement;
private void Start()
{
// Change which graph asset is used at runtime
placement.Graph = Resources.Load<PPGGraphAsset>("Graphs/ForestGraph");
placement.Seed = Random.Range(0, int.MaxValue);
// Execute the graph and spawn results
placement.Generate();
}
private void OnGUI()
{
if (GUILayout.Button("Regenerate"))
{
placement.Seed = Random.Range(0, int.MaxValue);
placement.Generate();
}
if (GUILayout.Button("Clear"))
placement.Cleanup();
}
}Generation with progress feedback
Generate() accepts an optional progress callback. Use it to drive a loading bar or to log long-running node names.
csharp
placement.Generate((nodeName, progress) =>
{
Debug.Log($"[PPG] {nodeName}: {progress:P0}");
loadingBar.value = progress;
});The callback signature is Action<string, float> — node name and normalized progress [0, 1].
Inspector-serialized properties
These are settable from code or via the Inspector:
| Property | Type | Description |
|---|---|---|
Graph | PPGGraphAsset | The graph asset to execute. Setting this also calls SyncBindings(). |
Seed | int | Base seed for all randomized nodes in the graph. Default: 42. |
GenerateOnStart | bool | If true, Generate() is called automatically in Start() during Play Mode. |
Runtime-only properties
| Property | Type | Description |
|---|---|---|
IsGenerated | bool | true after a successful Generate(), reset by Cleanup(). |
ManagedResources | PPGManagedResource | Tracks spawned GameObjects so they can be destroyed atomically by Cleanup(). |
Bindings | List<PPGComponentBinding> | Per-slot object bindings (assigned in the Inspector, indexed by slot GUID). |
ParameterOverrides | List<PPGParameterOverride> | Per-parameter value overrides for exposed graph parameters. |
Key methods
| Method | Description |
|---|---|
Generate(onProgress?) | Cleans up any existing generation, then executes the graph. Logs a warning if no graph is assigned. |
Cleanup() | Destroys all spawned objects tracked by ManagedResources, disposes the last result, and resets IsGenerated. |
SyncBindings() | Reconciles the Bindings list with the binding slots defined in the current graph asset. Called automatically when Graph is set. |
SyncParameterOverrides() | Reconciles the ParameterOverrides list with the exposed parameters in the current graph asset. |
GetBoundObject(slotGuid) | Returns the UnityEngine.Object bound to a specific slot GUID, or null. |
SyncAfterUndoRedo() | Called by the Editor to reconcile runtime state after Undo/Redo. Not needed in Play Mode. |
Lifecycle
Awake / OnEnable
└─> (nothing automatic)
Start [Play Mode only]
└─> GenerateOnStart == true → Generate()
Generate()
├─> Cleanup() (destroy previous output)
├─> SyncBindings()
├─> SyncParameterOverrides()
└─> PPGGraphExecutor.Execute(...)
OnDestroy
└─> Cleanup()PPGGraphAsset
PPGGraphAsset is the ScriptableObject that represents the graph data. Create one via Assets > Create > Procedural Placement Graph > Graph Asset.
You rarely need to manipulate a graph asset at runtime — assign it to PPGComponent.Graph and let the component drive execution. The properties below are useful for editor tooling or runtime introspection.
csharp
// Load an asset from Resources and inspect its structure
var graph = Resources.Load<PPGGraphAsset>("Graphs/ForestGraph");
Debug.Log($"Nodes: {graph.Nodes.Count}");
Debug.Log($"Edges: {graph.Edges.Count}");
Debug.Log($"Binding slots: {graph.BindingSlots.Count}");
Debug.Log($"Exposed parameters: {graph.ExposedParameters.Count}");Key members
| Member | Type | Description |
|---|---|---|
Nodes | IReadOnlyList<PPGNode> | All nodes in the graph. |
Edges | IReadOnlyList<PPGEdge> | All connections between ports. |
Comments | IReadOnlyList<PPGComment> | Editor-only comment boxes. |
Notes | IReadOnlyList<PPGNote> | Editor-only sticky notes. |
BindingSlots | List<PPGBindingSlot> | Named slots that accept external UnityEngine.Object references from a PPGComponent. |
ExposedParameters | List<PPGExposedParam> | Node fields promoted to graph-level parameters, overridable per PPGComponent. |
AddBindingSlot(name, type) | Returns PPGBindingSlot | Adds a new binding slot (Editor use). |
PPGGraphExecutor (internal)
PPGGraphExecutor is internal sealed — it is driven by PPGComponent and you do not instantiate it directly. Understanding its contract is useful if you build tooling that wraps PPGComponent.
What Execute returns
PPGComponent.Generate() calls executor.Execute(graph, component, seed, onProgress) and stores the result internally. The only observable surface at runtime is:
PPGComponent.IsGenerated— overall success flag.- The spawned GameObjects tracked in
PPGComponent.ManagedResources.
Execution result internals
PPGGraphExecutionResult (internal) carries:
| Field | Type | Description |
|---|---|---|
Success | bool | false if any node threw an unhandled exception. |
ErrorMessage | string | Human-readable error description when Success == false. |
OutputData | PPGDataCollection | Final output data from the graph's output node. |
NodeOutputs | Dictionary<string, PPGDataCollection> | Per-node outputs keyed by node GUID. Used for editor preview. |
NodeExecutionTimes | Dictionary<string, double> | Per-node execution time in milliseconds. |
CacheHitNodes | HashSet<string> | GUIDs of nodes served from the node cache (not re-executed). |
PPGGraphExecutionResult implements IDisposable. PPGComponent.Cleanup() calls Dispose() to release native buffers owned by PPGPointData instances.
Common Patterns
Regenerate when a property changes
csharp
private PPGComponent placement;
public void SetDensity(float density)
{
// Find the override for the "Density" exposed parameter
foreach (var o in placement.ParameterOverrides)
{
if (o.paramGuid == densityParamGuid)
{
o.jsonValue = density.ToString("R");
o.isOverridden = true;
break;
}
}
placement.Generate();
}Assign bindings at runtime
csharp
// Swap the mesh asset bound to a Binding slot without reassigning the graph
foreach (var binding in placement.Bindings)
{
if (binding.slotGuid == treeMeshSlotGuid)
{
binding.boundObject = newTreeMesh;
break;
}
}
placement.Generate();Lazy generation in Edit Mode
PPGComponent uses [ExecuteAlways], so Generate() works in Edit Mode. Guard against unintended generation during domain reload with IsGenerated:
csharp
if (!placement.IsGenerated)
placement.Generate();