TransformHandle API examples
Code examples that demonstrate the difference between Transform and TransformHandle API.
阅读时间4 分钟最后更新于 12 小时前
This section contains code examples that demonstrate the difference between and API.
TransformTransformHandleWorking with TransformHandle API
Because is a struct, you must assign it to a local variable before you can modify its properties. Modifying a property directly using a call results in a compiler error. This is because property accessors for structs return a copy of the struct, not a reference to it.
TransformHandlegameObject.transformHandleFor example, use the following approach to set the position of a property:
TransformHandle handle = transformHandle;handle.position = handle.position + Vector3.one;
You can call methods directly on the property:
// Methods can be called directlytransformHandle.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
To get a from a component, use the following code:
TransformHandletransformtransform.GetTransformHandle()
Example 1: Basic transform operations
Example using API:
Transformpublic class PlayerMovement : MonoBehaviour{ public Transform target; public Transform parentObject; void Update() { // Move position transform.position = transform.position + Vector3.forward * Time.deltaTime; // Look at target if (target != null) transform.LookAt(target); // Set parent transform.SetParent(parentObject); // Check hierarchy if (transform.IsChildOf(parentObject)) Debug.Log("Is child of parent"); }}
Example using API:
TransformHandlepublic class PlayerMovement : MonoBehaviour{ public Transform target; // Still use Transform for serialization public Transform parentObject; void Update() { // Get TransformHandle (required for struct operations) TransformHandle selfHandle = transformHandle; // Move position (must store in variable first) selfHandle.position = selfHandle.position + Vector3.forward * Time.deltaTime; // Look at target if (target != null) transformHandle.LookAt(target.transformHandle); // Set parent transformHandle.SetParent(parentObject.transformHandle); // Check hierarchy if (transformHandle.IsChildOf(parentObject.transformHandle)) Debug.Log("Is child of parent"); }}
Example 2: Hierarchy Navigation
Example using API:
Transformvoid ExploreHierarchy(Transform root){ Debug.Log($"Root: {root.name}, Children: {root.childCount}"); // Iterate through children foreach (Transform child in root) { Debug.Log($"Child: {child.name}"); ExploreHierarchy(child); // Recursive } // Get parent if (root.parent != null) Debug.Log($"Parent: {root.parent.name}");}
Example using API:
TransformHandlevoid ExploreHierarchy(TransformHandle root){ Debug.Log($"Root children count: {root.childCount}"); // Iterate through direct children foreach (TransformHandle child in root.DirectChildren) { Debug.Log($"Child ID: {child.id}"); ExploreHierarchy(child); // Recursive } // Get parent if (root.parent.IsValid()) Debug.Log($"Has parent: {root.parent.id}");}
Example 3: Hierarchy operations, batch operations, custom iteration
Example using API:
TransformHandleusing UnityEngine;// Demonstrates advanced features of the TransformHandle API, including// state management, batch operations, and manual hierarchy iteration.public class TransformHandleAdvancedFeatures : MonoBehaviour{ // Assign a prefab in the Inspector. public GameObject childPrefab; void Start() { // Each method demonstrates a different set of features. DemonstrateHandleStateAndManagement(); DemonstrateBatchOperations(); DemonstrateManualIteration(); } // Covers checking handle validity, parent status, and un-parenting. private void DemonstrateHandleStateAndManagement() { Debug.Log("--- Part 1: Hierarchy management ---"); if (childPrefab == null) { Debug.LogWarning("Child prefab not assigned. Skipping Part 1."); return; } // Create a child object to work with. GameObject childGo = Instantiate(childPrefab, transform); TransformHandle childHandle = childGo.transformHandle; // 1. Use HasParent() for a direct boolean check. Debug.Log($"Does child have a parent? {childHandle.HasParent()}"); // 2. Un-parent the object by setting its parent to TransformHandle.None. Debug.Log("Un-parenting the child..."); childHandle.parent = TransformHandle.None; Debug.Log($"Child's parent is now None: " + $"{childHandle.parent == TransformHandle.None}"); // 3. Use IsValid() to check if a handle points to a valid object. Debug.Log($"Is the handle valid before destroying? {childHandle.IsValid()}"); // Destroy the GameObject the handle was pointing to. Destroy(childGo); // NOTE: IsValid() will return false for this handle in the next frame, // as object destruction is delayed until the end of the current frame. // This check demonstrates the intended use case for preventing errors. if (!childHandle.IsValid()) { Debug.Log("Handle is no longer valid after object was destroyed."); } } // Shows how to use batch operations for improved performance. private void DemonstrateBatchOperations() { Debug.Log("\n--- Part 2: Batch operations ---"); TransformHandle handle = transformHandle; var localPoints = new Vector3[] { Vector3.up, Vector3.right, Vector3.forward }; Debug.Log($"Local point [0] before TransformPoints: {localPoints[0]}"); // TransformPoints modifies the array in-place, which is more efficient // than transforming each point individually in a loop. handle.TransformPoints(localPoints); Debug.Log($"World point [0] after TransformPoints: {localPoints[0]}"); } // Demonstrates how to manually iterate through children with an enumerator. private void DemonstrateManualIteration() { Debug.Log("\n--- Part 3: Custom iteration ---"); // Setup: Create some temporary children for the iteration demo. var child1 = new GameObject("Child_A"); var child2 = new GameObject("Child_B"); child1.transform.SetParent(transform); child2.transform.SetParent(transform); // GetDirectChildrenEnumerator provides fine-grained control over iteration. Debug.Log("Iterating with GetDirectChildrenEnumerator:"); var enumerator = transformHandle.GetDirectChildrenEnumerator(); while (enumerator.MoveNext()) { TransformHandle currentChild = enumerator.Current; Debug.Log($"Found child via enumerator."); } // Clean up the temporary objects created for this demonstration. Destroy(child1); Destroy(child2); }}