public static void ShowTab(CharacterControllerBase a_CharacterController)
    {
        if (a_CharacterController == null)
        {
            GUILayout.Label("CharacterController script not found on object", EditorStyles.boldLabel);
            return;
        }
        CapsuleMovingColliderSolver movingColliderSolver = a_CharacterController.GetComponent <CapsuleMovingColliderSolver>();

        if (movingColliderSolver)
        {
            SerializedObject solverObject = new SerializedObject(movingColliderSolver);
            EditorGUI.BeginChangeCheck();

            float prevLabelWidth = EditorGUIUtility.labelWidth;
            EditorGUIUtility.labelWidth += 120.0f;

            GUILayout.Label("Handling moving colliders", EditorStyles.boldLabel);
            GUILayout.Space(4.0f);

            EditorHelp.SerializeRelativeField(solverObject, "m_ApplyLastMovementAsVelocity", "Should the character inherit velocity from the moving object it was connected with, if the character loses connection with that object? For example: If the character jumps from a moving platform, should it keep the velocity of the moving platform", "Inherit velocity from moving platforms");
            if (solverObject.FindProperty("m_ApplyLastMovementAsVelocity").boolValue)
            {
                EditorHelp.SerializeRelativeField(solverObject, "m_DisableDownwardsLastMovement", "If the character inherits velocity from the moving object, should it prevent getting any downwards velocity? If the character is jumping from a platform that is moving down, should it ignore the downward velocity (checked), or should it also inherit that (unchecked)", "Inherit downward velocity or ignore it");
            }
            EditorHelp.SerializeRelativeField(solverObject, "m_UseEscapeAcceleration", "Should this character detach from a moving platform if the acceleration is too large? For example: if a character is standing on a platform which suddenly drops down, should the character detach from that platform (checked), or should the character stick to that platform (unchecked). Does not work if the platform is (partially) moving in the direction of the character (if a platform the character is standing on suddenly moves up, the character will stay connected)", "Detach from fast moving platforms");
            if (solverObject.FindProperty("m_UseEscapeAcceleration").boolValue)
            {
                EditorHelp.SerializeRelativeField(solverObject, "m_EscapeAcceleration", "If the above is checked, what is the acceleration needed for the character to detach? If the character is standing on a platform that moves away, how fast should it drop before the character detaches?", "Acceleration needed to detach");
            }

            EditorGUIUtility.labelWidth = prevLabelWidth;

            if (EditorGUI.EndChangeCheck())
            {
                solverObject.ApplyModifiedProperties();
            }
        }
        else
        {
            GUILayout.Label("CapsuleMovingColliderSolver script not found on object", EditorStyles.boldLabel);
        }
    }
    public static bool IsCharacterAlright(GameObject a_Object)
    {
        if (a_Object == null)
        {
            return(false);
        }
        GroundedCharacterController character = a_Object.GetComponent <GroundedCharacterController>();

        if (character == null)
        {
            return(false);
        }
        ControlledCapsuleCollider controlledCapsuleCollider = a_Object.GetComponent <ControlledCapsuleCollider>();

        if (controlledCapsuleCollider == null)
        {
            return(false);
        }
        PlayerInput input = a_Object.GetComponent <PlayerInput>();

        if (input == null)
        {
            return(false);
        }
        if (!input.DoesInputExist("Move") || !input.DoesInputExist("Jump"))
        {
            return(false);
        }
        AbilityModuleManager abilityModuleManager = a_Object.GetComponent <AbilityModuleManager>();

        if (abilityModuleManager == null)
        {
            return(false);
        }
        CapsuleMovingColliderSolver capsuleMovingColliderSolver = a_Object.GetComponent <CapsuleMovingColliderSolver>();

        if (capsuleMovingColliderSolver == null)
        {
            return(false);
        }
        CapsuleCollider capsuleCollider = a_Object.GetComponent <CapsuleCollider>();

        if (capsuleCollider == null)
        {
            return(false);
        }
        Rigidbody rigidbody = a_Object.GetComponent <Rigidbody>();

        if (rigidbody == null)
        {
            return(false);
        }
        if (rigidbody.constraints != RigidbodyConstraints.FreezeAll || rigidbody.useGravity != false || rigidbody.angularDrag != 0.0f)
        {
            return(false);
        }
        CapsuleVolumeIntegrity volumeIntegrity = a_Object.GetComponent <CapsuleVolumeIntegrity>();

        if (volumeIntegrity == null)
        {
            return(false);
        }

        SerializedObject serializedObject = new SerializedObject(character);

        if (serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue == null)
        {
            return(false);
        }
        if (serializedObject.FindProperty("m_AbilityManager").objectReferenceValue == null)
        {
            return(false);
        }

        serializedObject = new SerializedObject(controlledCapsuleCollider);
        if (serializedObject.FindProperty("m_CapsuleMovingColliderSolver").objectReferenceValue == null)
        {
            return(false);
        }
        if ((1 << a_Object.layer & serializedObject.FindProperty("m_LayerMask").intValue) != 0 ||
            (1 << LayerMask.NameToLayer("Ignore Raycast") & serializedObject.FindProperty("m_LayerMask").intValue) != 0)
        {
            return(false);
        }

        serializedObject = new SerializedObject(input);
        if (serializedObject.FindProperty("m_CharacterController").objectReferenceValue == null)
        {
            return(false);
        }

        serializedObject = new SerializedObject(capsuleMovingColliderSolver);
        if (serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue == null)
        {
            return(false);
        }

        serializedObject = new SerializedObject(volumeIntegrity);
        if (serializedObject.FindProperty("m_RigidBody").objectReferenceValue == null)
        {
            return(false);
        }
        if (serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue == null)
        {
            return(false);
        }
        if (serializedObject.FindProperty("m_CapsuleCollider").objectReferenceValue == null)
        {
            return(false);
        }

        return(true);
    }
    static void FixCharacterOnObject(GameObject a_Object)
    {
        //Find, or create missing components
        GroundedCharacterController character = a_Object.GetComponent <GroundedCharacterController>();

        if (character == null)
        {
            character = a_Object.AddComponent <GroundedCharacterController>();
        }
        ControlledCapsuleCollider controlledCapsuleCollider = a_Object.GetComponent <ControlledCapsuleCollider>();

        if (controlledCapsuleCollider == null)
        {
            controlledCapsuleCollider = a_Object.AddComponent <ControlledCapsuleCollider>();
        }
        PlayerInput input = a_Object.GetComponent <PlayerInput>();

        if (input == null)
        {
            input = a_Object.AddComponent <PlayerInput>();
        }
        input.EnsureJumpAndMoveInputsAreSet();
        AbilityModuleManager abilityModuleManager = a_Object.GetComponent <AbilityModuleManager>();

        if (abilityModuleManager == null)
        {
            abilityModuleManager = a_Object.AddComponent <AbilityModuleManager>();
        }
        CapsuleMovingColliderSolver capsuleMovingColliderSolver = a_Object.GetComponent <CapsuleMovingColliderSolver>();

        if (capsuleMovingColliderSolver == null)
        {
            capsuleMovingColliderSolver = a_Object.AddComponent <CapsuleMovingColliderSolver>();
        }
        CapsuleCollider capsuleCollider = a_Object.GetComponent <CapsuleCollider>();

        if (capsuleCollider == null)
        {
            capsuleCollider = a_Object.AddComponent <CapsuleCollider>();
        }
        Rigidbody rigidbody = a_Object.GetComponent <Rigidbody>();

        if (rigidbody == null)
        {
            rigidbody = a_Object.AddComponent <Rigidbody>();
        }
        rigidbody.constraints = RigidbodyConstraints.FreezeAll;
        rigidbody.useGravity  = false;
        rigidbody.angularDrag = 0.0f;
        CapsuleVolumeIntegrity volumeIntegrity = a_Object.GetComponent <CapsuleVolumeIntegrity>();

        if (volumeIntegrity == null)
        {
            volumeIntegrity = a_Object.AddComponent <CapsuleVolumeIntegrity>();
        }


        //Link up the components to one another, using the serializedobject interface
        SerializedObject serializedObject = new SerializedObject(character);

        serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue = controlledCapsuleCollider as ControlledCollider;
        serializedObject.FindProperty("m_AbilityManager").objectReferenceValue     = abilityModuleManager;
        serializedObject.ApplyModifiedProperties();

        serializedObject = new SerializedObject(controlledCapsuleCollider);
        serializedObject.FindProperty("m_CapsuleMovingColliderSolver").objectReferenceValue = capsuleMovingColliderSolver;
        if ((1 << a_Object.layer & serializedObject.FindProperty("m_LayerMask").intValue) != 0 ||
            (1 << LayerMask.NameToLayer("Ignore Raycast") & serializedObject.FindProperty("m_LayerMask").intValue) != 0)
        {
            serializedObject.FindProperty("m_LayerMask").intValue = ~((1 << a_Object.layer) + (1 << LayerMask.NameToLayer("Ignore Raycast")));
        }
        serializedObject.ApplyModifiedProperties();

        serializedObject = new SerializedObject(input);
        serializedObject.FindProperty("m_CharacterController").objectReferenceValue = character as CharacterControllerBase;
        serializedObject.ApplyModifiedProperties();

        serializedObject = new SerializedObject(capsuleMovingColliderSolver);
        serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue = controlledCapsuleCollider;
        serializedObject.ApplyModifiedProperties();

        serializedObject = new SerializedObject(volumeIntegrity);
        serializedObject.FindProperty("m_RigidBody").objectReferenceValue          = rigidbody;
        serializedObject.FindProperty("m_ControlledCollider").objectReferenceValue = controlledCapsuleCollider;
        serializedObject.FindProperty("m_CapsuleCollider").objectReferenceValue    = capsuleCollider;
        serializedObject.ApplyModifiedProperties();
    }