public override void OnInspectorGUI()
    {
        DimensionObject dimensionObject = (DimensionObject)target;

        serializedObject.Update();

        DebugField();

        channelSettingsShown = EditorGUILayout.Foldout(channelSettingsShown, "Channel settings:");
        if (channelSettingsShown)
        {
            EditorGUI.indentLevel++;
            EditorGUILayout.PropertyField(useAdvancedChannelLogic, new GUIContent("Use advanced channel logic"));
            if (useAdvancedChannelLogic.boolValue)
            {
                EditorGUILayout.PropertyField(channelLogic, new GUIContent("Channel logic: "));
                if (GUILayout.Button("Apply"))
                {
                    dimensionObject.ValidateAndApplyChannelLogic();
                }
            }
            else
            {
                EditorGUILayout.IntSlider(channel, 0, DimensionObject.NUM_CHANNELS - 1, new GUIContent("Channel: "));
            }

            EditorGUILayout.PropertyField(reverseVisibilityStates);
            EditorGUI.indentLevel--;
        }

        AddSeparator();

        if (collisionMatrixValid)
        {
            CollisionMatrixWithHelpButton(ref collisionMatrixHelp);
            OptionalHelpBox(
                collisionMatrixHelp,
                "The row indicates the effective visibility state of this object, the column the effective visibility state of the other DimensionObject (other for non-DimensionObjects)." +
                "\n\nNOTE: If reverseVisibilityStates is enabled, the effective VisibilityState is flipped to match."
                );
            if (collisionMatrixShown)
            {
                EditorGUI.indentLevel++;
                const int cols = DimensionObject.COLLISION_MATRIX_COLS;
                const int rows = DimensionObject.COLLISION_MATRIX_ROWS;
                for (int i = 0; i < rows; i++)
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField(visibilityStateLabels[i], GUILayout.MaxWidth(80));
                    for (int j = 0; j < cols; j++)
                    {
                        GUILayout.Label(visibilityStateLabels[j]);
                        dimensionObject.collisionMatrix[i * cols + j] =
                            EditorGUILayout.Toggle(dimensionObject.collisionMatrix[i * cols + j]);
                        if (j < rows)
                        {
                            // Fix & reset collision matrices that are of the wrong size
                            if (Mathf.Max(j * cols + i, i * cols + j) >= dimensionObject.collisionMatrix.Length)
                            {
                                dimensionObject.collisionMatrix = new bool[] {
                                    true, false, false, false, false, false,
                                    false, true, false, false, false, false,
                                    false, false, true, false, true, true,
                                    false, false, false, true, true, true
                                };
                                EditorGUI.indentLevel--;
                                return;
                            }

                            dimensionObject.collisionMatrix[j * cols + i] =
                                dimensionObject.collisionMatrix[i * cols + j];
                        }
                    }

                    EditorGUILayout.EndHorizontal();
                }

                EditorGUI.indentLevel--;
            }

            AddSeparator();
        }

        otherOptionsShown = EditorGUILayout.Foldout(otherOptionsShown, "Other options:");
        if (otherOptionsShown)
        {
            EditorGUI.indentLevel++;
            EditorGUILayout.PropertyField(treatChildrenAsOneObjectRecursively);
            EditorGUILayout.PropertyField(ignoreChildrenWithDimensionObject);
            EditorGUILayout.PropertyField(ignorePartiallyVisibleLayerChanges);
            EditorGUILayout.PropertyField(disableColliderWhileInvisible);
            EditorGUI.indentLevel--;
        }

        AddSeparator();

        renderersAndCollidersShown = EditorGUILayout.Foldout(renderersAndCollidersShown, "Renderers and Colliders:");

        if (renderersAndCollidersShown)
        {
            EditorGUI.indentLevel++;
            EditorGUILayout.PropertyField(renderers);
            EditorGUILayout.PropertyField(colliders);
            EditorGUI.indentLevel--;
        }

        AddSeparator();

        visibilityStateShown = EditorGUILayout.Foldout(visibilityStateShown, "Visibility State:");
        if (visibilityStateShown)
        {
            EditorGUI.indentLevel++;

            EditorGUI.BeginDisabledGroup(true);
            VisibilityState effectiveVisibilityState = (VisibilityState)visibilityState.enumValueIndex;
            effectiveVisibilityState = reverseVisibilityStates.boolValue
                ? effectiveVisibilityState.Opposite()
                : effectiveVisibilityState;
            EditorGUILayout.EnumPopup("Effective Visibility:", effectiveVisibilityState);
            EditorGUI.EndDisabledGroup();

            EditorGUILayout.PropertyField(startingVisibilityState);
            EditorGUILayout.PropertyField(visibilityState);
            if ((VisibilityState)visibilityState.enumValueIndex != cachedVisibilityState)
            {
                cachedVisibilityState = (VisibilityState)visibilityState.enumValueIndex;
                if (Application.IsPlaying(target))
                {
                    dimensionObject.SwitchVisibilityState(cachedVisibilityState, true);
                }
            }
            EditorGUI.indentLevel--;
        }

        serializedObject.ApplyModifiedProperties();

        DEBUGShown = false;
    }