所以我对这一切还很陌生。我已经开始为 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);
}
}
}
}
任何帮助/建议将非常感激:)
我创建了代码的简化版本,以便您可以了解如何遍历节点来构建一组叶节点。
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 个空节点: