16 / 20
Packages/2D Parallax Pro/Runtime C# examples
DEVELOPER REFERENCE
16 / 20

Runtime C# examples

Nine complete scripts for movement, runtime layers, clocks, presets and control.

English guideSource: Unity 6000.3.13f1 · URP 17.x optional10 October 2026

Nine complete scripts from the supplied guide: a camera test helper and eight runtime/API examples. Keep references to the environment you intend to control; there is no package singleton or HTTP/API-key setup.

Before using an example#

Create a matching .cs file under your own scripts folder, attach the component, then assign its Inspector references. Custom asmdefs need ERAGANX.Parallax2D; sample-specific classes also need Samples/UI/Input dependencies.

Namespaces are grouped by purpose: ERAGANX.Parallax2D.Core, .Runtime, .Layers, .Scrolling, .Environment, .Lighting and .Effects. Use the namespaces shown by each script. Setters sanitize values; keep direct fields finite. Calls do not automatically enable all controllers or create missing art/materials/bands.

1. Test camera movement#

Use GuideCameraMove.cs on Main Camera for the first depth exercise. Disable/remove it when your production follow system owns movement.

C#
using UnityEngine;
public sealed class GuideCameraMove : MonoBehaviour
{
    public Vector2 velocity = new Vector2(1f, 0f);
    void LateUpdate()
    {
        transform.position +=
            (Vector3)(velocity * Time.deltaTime);
    }
}

Download GuideCameraMove.cs

2. Create a runtime layer#

Use a fresh environment and assign Manager, renderedCamera and a tileable sprite. For an already authored layer, keep its existing reference instead of adding a duplicate.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Core;
using ERAGANX.Parallax2D.Runtime;
using ERAGANX.Parallax2D.Layers;
public sealed class GuideRuntimeLayers : MonoBehaviour
{
    public Parallax2DManager manager;
    public Camera renderedCamera;
    public Sprite tileableSprite;
    public Parallax2DQualityController quality;
    private Parallax2DLayer hills;
    void Start()
    {
        if (!manager || !renderedCamera || !tileableSprite)
            return;
        manager.SetCamera(renderedCamera);
        hills = manager.AddLayer(tileableSprite,
            "Runtime Hills", LayerPlacement.Background);
        hills.SetSpeed(new Vector2(0.8f, 0.1f));
        hills.sortingOrder = -80;
        hills.SetLooping(LoopAxes.Horizontal);
        hills.SetVisible(true);
        if (quality) quality.Refresh();
    }
    public void ShowHills(bool show)
    {
        if (hills) hills.SetVisible(show);
    }
    public void RemoveHills()
    {
        if (manager && hills)
            manager.RemoveLayer(hills, destroyObject: true);
        hills = null;
        if (quality) quality.Refresh();
    }
}

Download GuideRuntimeLayers.cs

AddLayer creates a child SpriteRenderer/Layer. RemoveLayer defaults to destroyObject: false, retaining the disabled/unregistered object; RefreshLayers can register it again. Explicit true destroys in Play Mode. Refresh quality after runtime structural changes.

3. Endless runner background#

Keep the rendered camera stationary and enable Horizontal looping on tileable backgrounds. Set Auto Scroll Multiplier zero for gameplay ground layers that must remain still.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Core;
using ERAGANX.Parallax2D.Runtime;
using ERAGANX.Parallax2D.Layers;
public sealed class GuideEndlessRunner : MonoBehaviour
{
    public Parallax2DManager manager;
    public Camera renderedCamera;
    public Parallax2DLayer groundLayer;
    public float runSpeed = 6f;
    void Start()
    {
        if (!manager || !renderedCamera) return;
        manager.SetCamera(renderedCamera);
        manager.SetMotionMode(ParallaxMotionMode.AutoScroll);
        manager.SetScrollVelocity(new Vector2(runSpeed, 0f));
        manager.scrollPaused = false;
        if (groundLayer) groundLayer.autoScrollMultiplier = 0f;
    }
    public void SetRunSpeed(float speed)
    {
        runSpeed = Mathf.Max(0f, speed);
        if (manager)
            manager.SetScrollVelocity(new Vector2(runSpeed, 0f));
    }
    public void SetScrollPaused(bool paused)
    {
        if (manager) manager.scrollPaused = paused;
    }
}

Download GuideEndlessRunner.cs

At run speed six and multiplier one, factors 0.85/0.65/0.30 drift -0.9/-2.1/-4.2 world units/s. Scroll pause is independent from camera/player pause.

4. Clock calls and events#

Assign Clock. Pair subscriptions/unsubscriptions and avoid logging every frequent hour update.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Environment;
public sealed class GuideClockEvents : MonoBehaviour
{
    public Parallax2DTimeController clock;
    public float DisplayHour { get; private set; }
    void OnEnable()
    {
        if (!clock) return;
        DisplayHour = clock.Hour;
        clock.OnSunrise += HandleSunrise;
        clock.OnNightStarted += HandleNight;
        clock.OnTimeChanged += HandleTime;
    }
    void OnDisable()
    {
        if (!clock) return;
        clock.OnSunrise -= HandleSunrise;
        clock.OnNightStarted -= HandleNight;
        clock.OnTimeChanged -= HandleTime;
    }
    void HandleSunrise() { Debug.Log("Sunrise"); }
    void HandleNight() { Debug.Log("Night started"); }
    void HandleTime(float hour) { DisplayHour = hour; }
    public void SetNight()
    {
        if (!clock) return;
        clock.automatic = false;
        clock.SetTime(0f);
    }
    public void ResumeCycle()
    {
        if (!clock) return;
        clock.automatic = true;
        clock.Resume();
    }
}

Download GuideClockEvents.cs

Bind SetNight/ResumeCycle to UI Buttons. AdvanceHours(3) advances game hours; SetTime(savedHour, false) restores saved time without events.

5. Weather, lighting and effects#

Enable relevant sections and assign their resources in Edit Mode first. ApplyWeather only updates the Environment controller's assigned Wind/Fog/Cloud references; handle multiple independent effects explicitly.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Environment;
using ERAGANX.Parallax2D.Lighting;
using ERAGANX.Parallax2D.Effects;
public sealed class GuideAtmosphere : MonoBehaviour
{
    public Parallax2DEnvironmentController environment;
    public Parallax2DLightingController lighting;
    public Parallax2DCloudController clouds;
    public Parallax2DParticleController particles;
    public Parallax2DCelestialController celestial;
    public void SetStormMood()
    {
        if (environment)
            environment.ApplyWeather(1.2f, 0.65f, 0.9f);
        if (lighting)
        {
            lighting.SetSunlightIntensity(0.5f);
            lighting.SetMoonlightIntensity(0.3f);
        }
        if (clouds) clouds.velocity = new Vector2(0.6f, 0f);
    }
    public void SetClearMood()
    {
        if (environment)
            environment.ApplyWeather(0.25f, 0.1f, 0.3f);
        if (lighting) lighting.SetSunlightIntensity(1f);
    }
    public void UseLeaves()
    {
        if (!particles) return;
        particles.kind = AmbientParticleKind.Leaves;
        particles.Configure();
        particles.emissionRate = 5f;
    }
    public void ShowSunAndMoon(bool show)
    {
        if (celestial) celestial.SetVisible(show);
    }
}

Download GuideAtmosphere.cs

Fog density and cloud opacity/velocity are public fields, not invented setter methods. For example, set fog.enabled = true, fog.density = 0.4f or clouds.opacity = 0.8f on valid references. Retune particle emission after Configure.

6. Apply and capture presets#

Create and assign the preset assets. Cancel an active transition before instant application, and coordinate external clock ownership.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Runtime;
using ERAGANX.Parallax2D.Layers;
public sealed class GuidePresets : MonoBehaviour
{
    public Parallax2DManager manager;
    public Parallax2DLayer selectedLayer;
    public Parallax2DLayerPreset layerPreset;
    public Parallax2DEnvironmentPreset environmentPreset;
    public Parallax2DPreset compositePreset;
    public Parallax2DQualityController quality;
    private Parallax2DEnvironmentPreset sessionSnapshot;
    public void ApplyLayer()
    {
        if (layerPreset && selectedLayer)
            layerPreset.ApplyTo(selectedLayer);
    }
    public void ApplyEnvironment()
    {
        if (!environmentPreset || !manager) return;
        environmentPreset.ApplyTo(manager,
            createMissingLayers: false);
        if (quality) quality.Refresh();
    }
    public void ApplyComposite()
    {
        if (compositePreset && manager)
            compositePreset.ApplyTo(manager);
    }
    public void CaptureSession()
    {
        if (!manager) return;
        if (!sessionSnapshot)
            sessionSnapshot = ScriptableObject
                .CreateInstance<Parallax2DEnvironmentPreset>();
        sessionSnapshot.CaptureFrom(manager);
    }
    void OnDestroy()
    {
        if (sessionSnapshot) Destroy(sessionSnapshot);
    }
}

Download GuidePresets.cs

CaptureSession stores an in-memory ScriptableObject snapshot; it does not save an .asset file. Existing artwork is retained. Persistent capture requires Editor tooling.

7. Smooth environment transition#

Add Parallax2DTransition to the environment root, assign its Manager and prepare a matching Night Environment Preset. Assign the same Clock used by that Manager.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Runtime;
using ERAGANX.Parallax2D.Environment;
public sealed class GuideTransition : MonoBehaviour
{
    public Parallax2DTransition transition;
    public Parallax2DEnvironmentPreset nightPreset;
    public Parallax2DTimeController clock;
    private bool ownsClock;
    private bool savedAutomatic;
    public void BeginNight()
    {
        if (!transition || !nightPreset || !clock) return;
        if (!ownsClock) savedAutomatic = clock.automatic;
        ownsClock = true;
        clock.automatic = false;
        transition.TransitionTo(nightPreset, 3f,
            applyDiscreteSettingsOnComplete: true);
    }
    void Update()
    {
        if (ownsClock &&
            (!transition || !transition.IsTransitioning))
            RestoreClock();
    }
    public void StopTransition()
    {
        if (transition) transition.Cancel();
        RestoreClock();
    }
    void RestoreClock()
    {
        if (ownsClock && clock)
            clock.automatic = savedAutomatic;
        ownsClock = false;
    }
    void OnDisable()
    {
        if (ownsClock) StopTransition();
    }
}

Download GuideTransition.cs

BeginNight temporarily owns Automatic state, restoring it on completion/cancel/disable. Paused is controlled separately. See transition limits.

8. Quality, reset and camera switch#

Assign Manager/Quality and optional custom quality/alternate camera references.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Core;
using ERAGANX.Parallax2D.Runtime;
public sealed class GuideRuntimeControls : MonoBehaviour
{
    public Parallax2DManager manager;
    public Parallax2DQualityController quality;
    public Parallax2DQualityPreset customQuality;
    public Camera alternateCamera;
    public void LowQuality()
    {
        if (quality) quality.SetQuality(QualityTier.Low);
    }
    public void HighQuality()
    {
        if (quality) quality.SetQuality(QualityTier.High);
    }
    public void ApplyCustomQuality()
    {
        if (!quality || !customQuality) return;
        quality.customPreset = customQuality;
        quality.Apply();
    }
    public void SwitchCamera()
    {
        if (manager && alternateCamera)
            manager.SetCamera(alternateCamera,
                preservePositions: true);
    }
    public void RebaseAfterOriginShift()
    {
        if (manager) manager.Rebaseline();
    }
    public void ResetLayerGeometry()
    {
        if (manager) manager.ResetEnvironment();
    }
}

Download GuideRuntimeControls.cs

ResetEnvironment resets layer geometry/drift and rebases to the current camera, not clock, presets, particles, player or save state. SetCamera does not enable/disable rendered cameras. For floating origin, shift camera/gameplay/environment together before Rebaseline; float coordinates have finite precision.

9. Custom camera movement source#

Supply an unshaken position while keeping the real rendered camera assigned for tile coverage.

C#
using UnityEngine;
using ERAGANX.Parallax2D.Core;
public sealed class GuideCameraSource : MonoBehaviour,
    IParallaxCameraSource
{
    public Transform unshakenCameraTarget;
    public Vector3 CameraPosition => unshakenCameraTarget
        ? unshakenCameraTarget.position
        : transform.position;
}

Download GuideCameraSource.cs

Assign the component under Camera Adapter > Advanced > Movement Source; keep Override Position off unless it should take priority. CameraFrame.Position drives parallax; ViewPosition is the real camera position.

Manager normally samples and advances/evaluates in LateUpdate at execution order 10000. If you deliberately use a manual driver, disable Manager's automatic LateUpdate and advance once after camera movement:

C#
// In a manual LateUpdate driver; Manager automatic evaluation is disabled.
if (manager.cameraAdapter.TryGetFrame(Time.deltaTime, out var frame))
{
    manager.AdvanceScroll(Time.deltaTime);
    manager.Evaluate(frame);
}

Default setups need no extra Evaluate/Tick/Advance calls. Duplicating normal lifecycle updates can advance time/drift twice. These examples reproduce the supplied guide; this website does not claim new compilation/player tests.

Adapted from the supplied guide · PDF pages 11, 29–35, 37–38.View source guide ↗
Keep creating.ERAGAN STUDIO.

Search a topic, setting or method across all package guides.