Unity 6.3
0 онлайн 95 гостей 3 в системе
Вход
Программирование в Unity Шаг 144 из 210

TransfromHandle API примеры

В этом разделе содержатся примеры кода, демонстрирующие разницу между Transform и TransformHandle API.

Работа с TransformHandle API

Потому что TransformHandle — структура, поэтому перед изменением её свойств её нужно присвоить локальной переменной. Изменение свойства напрямую через gameObject.transformHandle вызов приводит к ошибке компиляции. Дело в том, что методы доступа к свойствам структур возвращают копию структуры, а не ссылку на неё.

Например, используйте следующий подход для установки положения свойства:

TransformHandle handle = transformHandle;
handle.position = handle.position + Vector3.one;

Вы можете вызывать методы непосредственно в свойстве:

// Methods can be called directly
transformHandle.SetPositionAndRotation(Vector3.zero, Quaternion.identity);

Чтобы получить TransformHandle из компонента transform, используйте следующий код:

transform.GetTransformHandle()

Пример 1: Основные операции преобразования

Пример использования Transform API:

public 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");
    }
}

Пример использования TransformHandle API:

public 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");
    }
}

Пример 2: Hierarchy Навигация

Пример использования Transform API:

void 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}");
}

Пример использования TransformHandle API:

void 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}");
}

Пример 3: Операции Hierarchy, пакетные операции, пользовательская итерация

Пример использования TransformHandle API:

using UnityEngine;

// Demonstrates advanced features of the TransformHandle API, including
// state management, batch operations, and manual hierarchy iteration.
public class AdvancedTransformHandleFeatures : 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);
    }
}

Дополнительные ресурсы