子类无法访问父类的实例? “当前上下文中不存在”

问题描述 投票:0回答:1

所以我对这一切还很陌生。我已经开始为 Unity 项目实现一个简单的八叉树。它由一个 Octree 父类、它的一个实例和一个 OctreeNode 子类组成

我目前正在尝试从 OctreeNode 子类访问 Octree 实例中的一些缓存的公共变量,但它抛出“名称‘oTree’在当前上下文中不存在”。

以前,我曾尝试直接从父类访问这些变量,而没有创建它的实例 - 这导致了不同的错误“非静态字段、方法或属性需要对象引用” Octree.property'”所以我尝试通过实例化该类来补救它。

现在我检查了一下,除了构造函数之外,oTree 实例似乎在任何地方都不可用...我的 C# 基础相当不完整,所以它可能是一些非常基础的东西😅

这里的错误出现在最后 3 个方法中 - 我已经注释了出现错误的行。

public class Octree
{
    public OctreeNode rootNode;
    public List<OctreeNode> LeafNodes { get; private set; }
    public float MinimumWidth { get; private set; }
    public int MaxDepth { get; private set; }

    public Octree(Vector3 center, Bounds bounds, int capacity = 5, float minimumWidth = .5f, int maxDepth = 5)
    {
        Octree oTree = this;
        oTree.rootNode = new OctreeNode(center, bounds, capacity);
        oTree.MinimumWidth = minimumWidth;
        oTree.MaxDepth = maxDepth;
        oTree.LeafNodes = new List<OctreeNode>();
    }

    public class OctreeNode
    {
        public Vector3 Center { get; private set; }
        public Bounds Bounds { get; private set; }
        public List<Vector3> Members { get; private set; }
        public OctreeNode[] Children { get; private set; }
        public List<OctreeNode> CurrentNeighbours { get; private set; }
        public int Capacity { get; private set; }


        public OctreeNode(Vector3 center, Bounds bounds, int capacity = 5)
        {
            Center = center;
            Bounds = bounds;
            Members = new List<Vector3>(capacity);
            Children = null;
            CurrentNeighbours = null;
            Capacity = capacity;
        }

        public bool IsLeaf()
        {
            return Children == null;
        }

        private bool IsPotentialNeighbour(OctreeNode other, float searchRadius)
        {
            // Bounds Checks
        }

        private void BuildNeighbourList(OctreeNode node, float searchRadius = 1f)
        {
            foreach (OctreeNode otherLeaf in oTree.LeafNodes)   // Error: oTree non-existent?
            {
                if (node != otherLeaf) 
                {
                    if (IsPotentialNeighbour(otherLeaf, searchRadius))
                    {
                        node.CurrentNeighbours.Add(otherLeaf);
                    }
                }
            }
        }

        // Initial Call
        private void BuildLeafNodeList()
        {
            List<OctreeNode> LeafNodes = oTree.LeafNodes;      // Error: oTree non-existent?
            OctreeNode root = oTree.rootNode;                  // Error: oTree non-existent?

            if (root.IsLeaf()) { LeafNodes.Add(root); return; }
            foreach (OctreeNode child in root.Children)
            {
                BuildLeafNodeList(child, LeafNodes);
            }
        }

        // Recursive Call
        private void BuildLeafNodeList(OctreeNode node, List<OctreeNode> LeafNodes)
        {
            if (node.IsLeaf()) { LeafNodes.Add(node); return; }

            foreach (OctreeNode child in node.Children)
            {
                BuildLeafNodeList(child, LeafNodes);
            }
        }
    }
}

任何帮助/建议将非常感激:)

c# unity-game-engine scoping recursive-datastructures octree
1个回答
0
投票

我创建了代码的简化版本,以便您可以了解如何遍历节点来构建一组叶节点。

public class Octree
{
    public OctreeNode RootNode { get; private set; }

    public Octree()
    {
        this.RootNode = new OctreeNode();
    }

    public Octree(OctreeNode rootNode)
    {
        this.RootNode = rootNode;
    }

    public class OctreeNode
    {
        private List<OctreeNode> Children = new List<OctreeNode>();

        public OctreeNode()
        { }
        
        public OctreeNode(IEnumerable<OctreeNode> children)
        {
            this.Children.AddRange(children);
        }

        public bool IsLeaf => this.Children.IsEmpty();

        public IEnumerable<OctreeNode> GetDescendantLeafNodes()
        {
            if (this.IsLeaf)
            {
                yield return this;
            }
            else
            {
                foreach (var child in this.Children)
                {
                    foreach (var leaf in child.GetDescendantLeafNodes())
                    {
                        yield return leaf;
                    }
                }
            }
        }
    }
}

我特意将孩子们设置为

private List<OctreeNode>
而不是数组。您可以实例化一个空列表来表示叶节点,而不是使用
null
,它有抛出
NullReferenceException
的习惯,并且您不希望外部代码更改树的成员。

这是一个示例树:

var octree =
    new Octree(
        new Octree.OctreeNode(
            new Octree.OctreeNode[]
            {
                new Octree.OctreeNode(
                    new Octree.OctreeNode[]
                    {
                        new Octree.OctreeNode(),
                        new Octree.OctreeNode(),
                    }),
                new Octree.OctreeNode(),
                new Octree.OctreeNode(),
                new Octree.OctreeNode(),
            }));

当我调用

octree.RootNode.GetDescendantLeafNodes()
时,我得到了预期的 5 个空节点:

© www.soinside.com 2019 - 2024. All rights reserved.