I've gotten to the stage of importing files from VRoid to Blender, however I'm coming across a somewhat perplexing issue.

VRoid will generate the bones and even colliders (though I wish that could be turned off), however while Blender recognizes the bones as valid, it won't mirror them even though they're named in reverse. If there is a way to fix this, what is the best approach?


1 Answer 1


I found a solution! This python script renames the bones so that Blender properly recognizes them:

bl_info = {
    "name": "VRM Swap Bone Names",
    "blender": (3, 4, 1),
    "category": "Object",

import bpy

class VRMSwapBoneNamesOperator(bpy.types.Operator):
    bl_idname = "object.vrmswapbonenames"
    bl_label = "VRM Swap Bone Names"
    bl_description ="Swap VRM style bone names to append _Left and _Right to all selected objects' vertex group names and bone names. Run this operator again to swap back to VRM style names with _L_ and _R_"
    bl_options = {'REGISTER', 'UNDO'}
    def execute(self, context):
        def replaceName(namedObject, mode):
            if "_L_" in namedObject.name and mode >= 0:
                namedObject.name = namedObject.name.replace("_L_","_d_")+"_Left"
                return 1
            elif "_R_" in namedObject.name and mode >= 0:
                namedObject.name = namedObject.name.replace("_R_","_d_")+"_Right"
                return 1
            elif "_d_" in namedObject.name and "_Left" in namedObject.name and mode <= 0:
                namedObject.name = namedObject.name.replace("_d_","_L_").removesuffix("_Left")
                return -1
            elif "_d_" in namedObject.name and "_Right" in namedObject.name and mode <= 0:
                namedObject.name = namedObject.name.replace("_d_","_R_").removesuffix("_Right")
                return -1
            return mode
        mode = 0
        for target in bpy.context.selected_objects:
            v_groups = target.vertex_groups
            for vg in v_groups:
                mode = replaceName(vg, mode)
            if target.type == 'ARMATURE':
                for b in target.data.bones:
                    mode = replaceName(b, mode)
        return {'FINISHED'}
    def invoke(self, context, event):
        return self.execute(context) 

def menu_func(self, context):

def register():

def unregister():
if __name__ == "__main__":

Source: https://gist.github.com/Ooseykins/ee55ca931ef91ef4e101a09fcb159977


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .