Drag and drop nightmare

Not sure if anyone else here is like me, and hate the whole “Drag and drop nodes in inspector” I hated that in Unity also, so I made a small extension helper to automatically do it for me, it probably dont work perfectly for multiple Nodes of the same type, since I hate to have to give up string values of the nodes I am attempting to get the name of the current node.

I haven’t tested it extensively yet, but a quick overview it does work.

public static T SetupNode<T>(this Node parent) where T : Node
{
    var childNodes = parent.GetChildren();
    try
    {
        if (!NodeTypeCount.ContainsKey(typeof(T)))
        {
            NodeTypeCount[typeof(T)] = 0;
        }

        var correctChild = childNodes.Where(child => child is T).ElementAt(NodeTypeCount[typeof(T)]);
        NodeTypeCount[typeof(T)]++;

        return parent.GetNodeOrNull<T>(new NodePath(correctChild.Name));
    }
    catch (Exception)
    {
        var nodeNames = childNodes.Select(s => s.Name);
        var message =
            $"No nodes of type {typeof(T).Name} with name found in {parent.Name}. The available nodes are: {string.Join(", ", nodeNames)}";
        parent.GetTree().Quit();
        throw new InvalidOperationException(message);
    }
}

Then it can be used like this:

    _animPlayerNode = this.SetupNode<AnimationPlayer>();
    _animPlayerNode2 = this.SetupNode<AnimationPlayer>();
    _sprite = this.SetupNode<Sprite3D>();
    _sprite2 = this.SetupNode<Sprite3D>();

    _animPlayerNode.RootNode = _sprite.GetPath();
    _animPlayerNode2.RootNode = _sprite2.GetPath();

Anyway, done with that rabbithole. Back to the course to learn godot!

1 Like

Here’s my solution to this problem. Just create a new NodeExtension.cs file and drop the following code:

public static class NodeExtension
{
    /// <summary>
    /// Find all nodes of type T in the scene tree.
    /// </summary>
    public static IEnumerable<T> FindNodes<T>(this Node3D self, bool includeInternal = false) where T : Node
    {
        return self.GetChildren(includeInternal).OfType<T>();
    }
    
    /// <summary>
    /// Find single node of type T in the scene tree. Optional filter by node name.
    /// </summary>
    public static T? FindNode<T>(this Node3D self, string? nodeName = null, bool includeInternal = false) where T : Node
    {
        return self.GetChildren(includeInternal)
            .Where(x => nodeName == null || x.Name == nodeName)
            .OfType<T>().FirstOrDefault();
    }
    
    /// <summary>
    /// Find single node of type T in the scene tree. Optional filter by node name.
    /// </summary>
    public static bool TryFindNode<T>(this Node3D self, out T? node, string? nodeName = null, bool includeInternal = false) where T : Node
    {
        node = self.GetChildren(includeInternal)
            .Where(x => nodeName == null || x.Name == nodeName)
            .OfType<T>().FirstOrDefault();
        
        return node != null;
    }
}

Usage:

        animationPlayer = this.FindNode<AnimationPlayer>()!;
        spriteNode = this.FindNode<Sprite3D>("Sprite3D")!;

        //or
        if(this.TryFindNode<Sprite3D>(node: out var mySprite))
            spriteNode = mySprite!;

You can search through all children via type and search a single instance by type and an optional name (for exaple if you have multiple Sprite3D Nodes and only want the “SwordSprite” Node.

Privacy & Terms