cd /news/developer-tools/floating-origin-to-handle-large-worl… · home topics developer-tools article
[ARTICLE · art-11310] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Floating origin to handle large worlds in Unity.

The article describes a Unity script called `FloatingOrigin.cs` that prevents precision errors in large game worlds by shifting the scene's origin when a reference object moves beyond a set distance threshold. The script can update all open scenes or just the active one, and it also adjusts the positions of particle systems, trail renderers, and line renderers to maintain visual consistency during the shift.

read2 min views27 publishedApr 6, 2020

FloatingOrigin.cs

  This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

Show hidden characters
// Based on the Unity Wiki FloatingOrigin script by Peter Stirling

// URL: http://wiki.unity3d.com/index.php/Floating_Origin

using UnityEngine;

using UnityEngine.SceneManagement;

public class FloatingOrigin : MonoBehaviour

{

    [Tooltip("Point of reference from which to check the distance to origin.")]

    public Transform ReferenceObject = null;

    [Tooltip("Distance from the origin the reference object must be in order to trigger an origin shift.")]

    public float Threshold = 5000f;

    [Header("Options")]

    [Tooltip("When true, origin shifts are considered only from the horizontal distance to orign.")]

    public bool Use2DDistance = false;

    [Tooltip("When true, updates ALL open scenes. When false, updates only the active scene.")]

    public bool UpdateAllScenes = true;

    [Tooltip("Should ParticleSystems be moved with an origin shift.")]

    public bool UpdateParticles = true;

    [Tooltip("Should TrailRenderers be moved with an origin shift.")]

    public bool UpdateTrailRenderers = true;

    [Tooltip("Should LineRenderers be moved with an origin shift.")]

    public bool UpdateLineRenderers = true;

    private ParticleSystem.Particle[] parts = null;

    void LateUpdate()

    {

        if (ReferenceObject == null)

            return;

        Vector3 referencePosition = ReferenceObject.position;

        if (Use2DDistance)

            referencePosition.y = 0f;

        if (referencePosition.magnitude > Threshold)

        {

            MoveRootTransforms(referencePosition);

            if (UpdateParticles)

                MoveParticles(referencePosition);

            if (UpdateTrailRenderers)

                MoveTrailRenderers(referencePosition);

            if (UpdateLineRenderers)

                MoveLineRenderers(referencePosition);

        }

    }

    private void MoveRootTransforms(Vector3 offset)

    {

        if (UpdateAllScenes)

        {

            for (int z = 0; z < SceneManager.sceneCount; z++)

            {

                foreach (GameObject g in SceneManager.GetSceneAt(z).GetRootGameObjects())

                    g.transform.position -= offset;

            }

        }

        else

        {

            foreach (GameObject g in SceneManager.GetActiveScene().GetRootGameObjects())

                g.transform.position -= offset;

        }

    }

    private void MoveTrailRenderers(Vector3 offset)

    {

        var trails = FindObjectsOfType<TrailRenderer>() as TrailRenderer[];

        foreach (var trail in trails)

        {

            Vector3[] positions = new Vector3[trail.positionCount];

            int positionCount = trail.GetPositions(positions);

            for (int i = 0; i < positionCount; ++i)

                positions[i] -= offset;

            trail.SetPositions(positions);

        }

    }

    private void MoveLineRenderers(Vector3 offset)

    {

        var lines = FindObjectsOfType<LineRenderer>() as LineRenderer[];

        foreach (var line in lines)

        {

            Vector3[] positions = new Vector3[line.positionCount];

            int positionCount = line.GetPositions(positions);

            for (int i = 0; i < positionCount; ++i)

                positions[i] -= offset;

            line.SetPositions(positions);

        }

    }

    private void MoveParticles(Vector3 offset)

    {

        var particles = FindObjectsOfType<ParticleSystem>() as ParticleSystem[];

        foreach (ParticleSystem system in particles)

        {

            if (system.main.simulationSpace != ParticleSystemSimulationSpace.World)

                continue;

            int particlesNeeded = system.main.maxParticles;

            if (particlesNeeded <= 0)

                continue;

            // ensure a sufficiently large array in which to store the particles

            if (parts == null || parts.Length < particlesNeeded)

            {

                parts = new ParticleSystem.Particle[particlesNeeded];

            }

            // now get the particles

            int num = system.GetParticles(parts);

            for (int i = 0; i < num; i++)

            {

                parts[i].position -= offset;

            }

            system.SetParticles(parts, num);

        }

    }

}
── more in #developer-tools 4 stories · sorted by recency
── more on @unity 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/floating-origin-to-h…] indexed:0 read:2min 2020-04-06 ·