I am stoked that you showed this image because it has caused me to visualize a very cool idea.
The screen that you have captured as an image will be something more of a background for this 3D scene with the spheres.
For each of the Body Mind and Soul, there will not be a 2D button, as generally are used to do stats, but a 3D sphere. The 3D spheres simply are used like buttons, each sphere generally aligned in front of each word it represents. The textures of the spheres match the vibe in some way of the image you showed us, like having a purple-toned color, and they could slowly spin or something.
This is how the 'buttons' work:
Each sphere is a MeshInstance naturally, parented to a kinematic body, along with a spherical CollisionShape.
Using the mouse_enter mouse_exit signal connection functions that are inherited by KinematicBody, you make them interact the following way:
When the mouse enters a sphere and the mouse isnt held down, it grows. That is, it immediately starts growing. The rate of growth is determined by how close the mouse position is to the origin of the sphere's transform.
Then, when the mouse enters the sphere and the mouse button is HELD DOWN, it shrinks.
something like this:
extends KinematicBody
func _ready():
connect('mouse_enter',self,'start')
connect('mouse_exit',self,'stop')
set_process_input(true)
func start():
set_process(true)
func stop():
set_process(false)
func _process(delta):
if mouse button is NOT held down:
scale_sphere_by_distance(1)
if mouse_Button IS held down:
scale_sphere_by_distance(-1)
func scale_sphere_by_distance(up_or_down):
if scale < max_scale && scale > min_scale:
scale_modifier = roots_current_camera.project_position(mouse_position).distance_to(sphere.get_global_transform().origin)
new_scale = sphere.get_scale() + (scale_modifier * up_or_down)
sphere.set_scale(new_scale)
Now, consider this:
instead of using an abstract 'stat' number, just use the sphere's scale as the stat. Why make up a number when you already have a number? its easier to convert one of the scalar coordinates of the sphere to the stat instead of making up some arbitrary scale. trust me on this!
How do you know that the spheres are balanced and you don't just fill them up all the way?! Well I've thought of a cool design around that. If any of the spheres are touching, the screen will get a slight red tint, and the user cant progress the screen. If none of the spheres are touching, then the stats will be considered 'balanced'.
Something like this to make the screen red (still on kinematicbody script)
connect('body_enter',self,'screen_color_set_red')
connect('body_exit',self,screen_color_reset')
that way it detects when one of the other sphere bodies enters it
you can change the screen to red if you have set the camera to have an environment. I think that is easier than anything else because the object instance used is the camera, which already exists. not sure of the exact parameters.
anyway, finally I will supply an image that I conceptualize using your screen shot:

