SpringBoneCollision and its limitations

Godot Version: 4.6.3 stable

Hey yall! First post here, hope this is alright. I am working with SpringBoneSimulator3D in a semi unusual way. In short, I wanted a “flying, snakelike” character as one of my games central protagonists. The immediate challenge in this was finding a way to create the procedural animation where the body of the snake follows the path of the head, like a 3D version of the classic game Snake.

Starting with a simple, cylinder-like mesh, I tried numerous approaches to snake animation including:

  • Trying to write an extremely complex “bend by vector” shader and giving up on that halfway through- Normals get way too distorted and there’s no way to factor for collisions
  • Manually adjusting snake “segments” in GDScript. This works much better for collisions but is cpu heavy and it’s difficult to get the segments to blend nicely or look good at all.
  • Filling my snake up with a chain of bones, then manually animating those bones similar to the above. This actually kind of worked in a clunky way, but the challenges with the script were going to be ongoing.

And then I realized that I can just add a SpringBoneSimulator3D to my snake, and the default settings automatically do everything I could have wanted in terms of animation. The snake twists and rolls majestically. In my hand coded versions I was throwing out roll, vertical looping etc, with SpringBones it all happens without a single line of code.

Attached - a photo of my beautiful test snake

The only issue is collisions. Collisions for springbones are meant to happen internally- the expected use case is for hair, clothes or a tail bouncing off of geometry attached to the same skeleton. In my use case, I want my SpringBone collisions to interact with regular collisions in the outside world.

What I’m testing right now is a janky-feeling-but-it-works manual setup that goes like this:

  • I add SpringBoneCollision objects to my scene, as children of a select Node3D. They don’t do anything without a SpringBoneSimulator3D parent, but they don’t throw errors either.
  • In my player character, the snake, I added a script to ready() which grabs all children of and reparents them to the internal SpringBoneSimulator.
  • Each SpringBoneCollision node has a tiny script on physics process that constantly resets its position and rotation to where they were at spawn. That way, the collisions stay locked to the world and don’t move and rotate to follow the player around.

Functionally, this is great. What I don’t know yet is how it will scale, so I guess the next step is to dump ~100 collisions into a level and see how it reacts. I might need to write a script that locates collisions within a radius and constantly updates which ones are active… unless Godot is smart enough to automatically skip collision checks that are out of range.

My question is: Has anyone else messed with anything like this or am I in unexplored territory? If there was someone on this forum with detailed technical advice about the internal workings of SpringBoneSimulator3D and SpringBoneCollision3D I would be really grateful to learn. Now is a great time to know if I’m accidentally doing this harder instead of smarter.

If anyone has tried anything similar to this before, or has experience with stress testing the spring bone system, I would love to hear about it. Thank you!

This seems way overcomplicated. I mean if it’s fun for you, go for it. I’d recommend you make a snake in Blender and animate it there, then import it.

As for collisions, you need to add a CollisionShape3D to the CharacterBody3D your snake is attached to, and that will handle world collisions.