You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity八叉树开发:如何用C#指针数组存储子节点ABB引用?

问题描述

我正在Unity中开发八叉树,希望每个节点拥有指向子节点ABB的指针数组。ABB结构体定义如下:

public struct ABB
{
    public float size;

    public float centerX;
    public float centerY;
    public float centerZ;

    public ABB(float size, float centerX, float centerY, float centerZ)
    {
        this.size = size;
        
        this.centerX = centerX;
        this.centerY = centerY;
        this.centerZ = centerZ;
    }
}

每个节点包含子节点数组:

public OctreeNode[] children = null;

我需要在Burst Job中使用子节点的ABB,但OctreeNode是类,不被Burst支持。存储ABB副本冗余,因此想存储子节点ABB的指针。我定义了指针数组:

public ABB*[] childBounds = null;

尝试如下代码赋值时出现错误:

if (children[0] == null)
{
    children[0] = new OctreeNode(new ABB(childLength, nodeBounds.centerX + -quarter, nodeBounds.centerY + quarter, nodeBounds.centerZ + -quarter), this, rootSeed);
    childBounds[0] = children[0].nodeBounds;
}

错误提示:

Cannot implicitly convert type AABB (children[0].nodeBounds) to AABB*

请问在C#中如何正确实现指针数组的赋值?

解决方案

核心问题

children[0].nodeBounds是值类型(ABB是结构体),直接访问会返回副本,无法直接转为指针。要获取其内存地址,需要固定该字段的内存位置,避免GC移动导致指针失效。

正确赋值方式

使用fixed关键字固定nodeBounds的内存地址,再获取指针:

if (children[0] == null)
{
    children[0] = new OctreeNode(new ABB(childLength, nodeBounds.centerX + -quarter, nodeBounds.centerY + quarter, nodeBounds.centerZ + -quarter), this, rootSeed);
    // 固定子节点nodeBounds的内存,获取指针
    fixed (ABB* boundsPtr = &children[0].nodeBounds)
    {
        childBounds[0] = boundsPtr;
    }
}

关键注意事项

  1. GC安全风险:OctreeNode是类,其对象在堆上的位置可能被GC移动,一旦移动,childBounds中的指针就会失效。如果八叉树节点生命周期短或会被频繁GC,这种方式存在崩溃风险。
  2. Burst兼容性优化:Burst对非托管内存的支持更稳定,建议改用NativeArray<ABB>存储所有边界,用整数索引代替指针——既避免指针安全问题,又完全符合Burst的使用规范:
    // 根节点或全局持有所有ABB的NativeArray
    public NativeArray<ABB> allBounds;
    // 子节点存储allBounds中的索引,而非指针
    public int[] childBoundsIndices = null;
    
    这种方式性能不逊于指针,且无需担心GC问题,是Unity Burst开发的最佳实践。

内容的提问来源于stack exchange,提问作者Hoogoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:15:36