The Unity script needs the Editor and the setup listed below. The separate C# companion practice runs in SharpRune without UnityEngine.
A point’s coordinate space is part of its meaning
Transform.localPosition describes a child relative to its parent, while Transform.position describes the corresponding point in world space. The parent transform can translate, rotate and scale the child coordinates. Treating both Vector3 values as interchangeable because they have the same type produces hard-to-explain offsets in cameras, prefabs and nested objects. Start with a simple hierarchy whose expected point can be calculated by hand, then change one parent property at a time. The general engine conversion is more than adding two position vectors.
Follow the specified parent-child setup
Create Parent at world ten, zero, zero with no rotation and unit scale, then Child at local one, zero, zero. Put TransformProbe on Child. Its initial log should distinguish local one, zero, zero from world eleven, zero, zero. The parent’s TransformPoint conversion of that local point should agree with the child’s world position. The script can be invoked through its context menu after a change, so you can compare the same child’s values without pretending the initial Start log updates automatically when the hierarchy is edited later.
The portable lab intentionally covers translation only
The companion uses an ordinary two-dimensional Point value, parent ten, three and local two, one. Adding coordinates gives world twelve, four, and subtracting the parent recovers two, one. The printed results are 12,4 and 2,1. This is a useful reversible translation check, but its assumptions exclude parent rotation, scale and a hierarchy of transforms. It is not a fake TransformPoint implementation. Keep the separate dimensions and numbers explicit instead of expecting its twelve, four output to match the real scene’s three-dimensional eleven, zero, zero setup.
Reparenting and scale can invalidate a translation shortcut
Rotating a parent changes which world direction a child’s local axis follows. Scaling changes the world displacement represented by one local unit. Reparenting can also require a deliberate decision about preserving world or local pose. A helper that merely adds positions cannot solve those general cases. Use supported Transform conversion APIs for real arbitrary transforms, and state whether an input is a point or a direction because translation should affect a point differently from a direction. Similar-looking vectors do not establish the same spatial contract.
Practice: isolate rotation from translation
Keep Child’s local position unchanged and rotate Parent around its Y axis in one experiment. Compare local and world logs and the TransformPoint result. Restore rotation before changing Parent’s scale in a separate experiment. Then move only Parent’s position. Write down which local value stays fixed and which world value should change before observing the scene. This isolates three transformations instead of making several changes and guessing which caused the apparent jump.
- Select the object that actually carries TransformProbe before invoking its context action.
- Avoid interpreting Euler-angle Inspector text as proof that every transform combination can be handled by simple coordinate addition.
Practice: verify the limited arithmetic contract
For an independent portable variation, choose a parent with negative coordinates and a local point at zero. Predict the world point, then recover local coordinates through subtraction. Add a second translation level and verify that adding all parent translations works under this deliberately translation-only model. Finally write a short explanation of why that result does not justify using the same formula after adding a rotated or scaled parent in Unity. An honest limited model is more useful than a broad helper whose unsupported cases are hidden.
- Test parent zero, local zero and negative values as separate arithmetic boundaries.
- Name values parentPosition, localPoint and worldPoint rather than using interchangeable variables named position.
Make every conversion explicit at the boundary
Spatial code becomes easier to review when each value names its coordinate space and each conversion belongs to a clear owner. The real script uses the engine’s hierarchy-aware TransformPoint; the portable lab proves only a small translation relationship. Neither path promises that all transforms are independent snapshots, because the hierarchy can change. When integrating movement, physics or prefab placement, specify whether each operation consumes local or world state and verify the actual parent configuration rather than correcting an offset with an unexplained numeric constant.
- The real baseline child has local (1,0,0) and world (11,0,0).
- The portable translation baseline prints 12,4 then 2,1 for its different two-dimensional inputs.
- Rotation, scale, reparenting, points and directions require explicit coordinate-space reasoning.
Unity Editor example
Set up in Unity 6
- Create Parent at world position (10,0,0), rotation zero and scale one.
- Create Child under Parent at local position (1,0,0) and attach TransformProbe.cs to Child.
- Enter Play mode and compare local (1,0,0) with world (11,0,0).
- Rotate Parent in a separate experiment, then invoke Log Coordinates from the component context menu.
- Restore rotation, change parent scale, and observe that a fixed local point has a different world point.
TransformProbe.cs
Download Unity script ↗using UnityEngine;
public sealed class TransformProbe : MonoBehaviour
{
private void Start() { LogCoordinates(); }
[ContextMenu("Log Coordinates")]
public void LogCoordinates()
{
Debug.Log("Local: " + transform.localPosition + ", World: " + transform.position, this);
if (transform.parent != null)
Debug.Log("Converted: " + transform.parent.TransformPoint(transform.localPosition), this);
}
}
What to observe in Unity
The initial setup reports different local and world coordinates, and TransformPoint agrees with the world point. Parent rotation or scale changes the conversion.
The console practice below isolates the C# logic. It does not run a Unity scene or emulate Unity engine callbacks.
C# companion practice
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
var parent = new Point(10, 3); var local = new Point(2, 1);
var world = new Point(parent.X + local.X, parent.Y + local.Y);
Console.WriteLine($"{world.X},{world.Y}");
Console.WriteLine($"{world.X - parent.X},{world.Y - parent.Y}");
readonly struct Point { public int X { get; } public int Y { get; } public Point(int x, int y) { X = x; Y = y; } }
C# practice output
12,4 2,1
The portable exercise is translation-only; Unity handles the full parent transform.