Unity-Technologies/UnityCsReference · error · ArgumentException

Type should derive from PlayModeView

Error message

Type should derive from PlayModeView

What it means

Thrown by PlayModeView.SwapMainWindow(Type type) when the provided type's direct base class is not exactly PlayModeView. The method performs a strict BaseType check (not an IsAssignableFrom check), so only types that directly inherit from PlayModeView are accepted. This is a design constraint ensuring the window serialization and view-cache mechanism works correctly.

Source

Thrown at Editor/Mono/PlayModeView/PlayModeView.cs:306

        }

        private string GetTypeName()
        {
            return GetType().ToString();
        }

        private Dictionary<string, string> ListsToDictionary(List<string> keys, List<string> values)
        {
#pragma warning disable UA2001 // The Banned API Analyzer produces compile errors for any new Linq code. This pre-existing usage has been suppressed, but should be rewritten if possible.
            var dict = keys.Select((key, val) => new { key, val = values[val] }).ToDictionary(x => x.key, x => x.val);
#pragma warning restore UA2001
            return dict;
        }

        protected internal void SwapMainWindow(Type type)
        {
            if (type.BaseType != typeof(PlayModeView))
                throw new ArgumentException("Type should derive from " + typeof(PlayModeView).Name);
            if (type.Name != GetType().Name)
            {
                var serializedViews = ListsToDictionary(m_SerializedViewNames, m_SerializedViewValues);

                // Clear serialized views so they wouldn't be serialized again
                m_SerializedViewNames.Clear();
                m_SerializedViewValues.Clear();

                var guid = GUID.Generate();
                var serializedViewPath = Path.GetFullPath(Path.Combine(m_ViewsCache, guid.ToString()));
                if (!Directory.Exists(m_ViewsCache))
                    Directory.CreateDirectory(m_ViewsCache);

                InternalEditorUtility.SaveToSerializedFileAndForget(new[] {this}, serializedViewPath, true);
                serializedViews.Add(GetTypeName(), serializedViewPath);

                PlayModeView window = null;
                if (serializedViews.ContainsKey(type.ToString()))

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Ensure the type you pass directly inherits from PlayModeView — use typeof(GameView) or typeof(SimulatorWindow) which are the built-in direct subclasses.
  2. If you have a custom view, make sure its class declaration is 'class MyView : PlayModeView' not 'class MyView : GameView'.
  3. Use PlayModeWindow.SetViewType with the enum value instead of calling SwapMainWindow directly, as it handles type resolution internally.

Example fix

// before
view.SwapMainWindow(typeof(MyCustomGameView)); // inherits GameView, not PlayModeView

// after
view.SwapMainWindow(typeof(GameView)); // direct subclass of PlayModeView
Defensive patterns

Strategy: type-guard

Type guard

static bool IsValidPlayModeViewType(Type type) => type != null && type.BaseType == typeof(PlayModeView);

Prevention

When it happens

Trigger: Calling SwapMainWindow with a type whose BaseType != typeof(PlayModeView). This includes types that inherit from GameView or SimulatorWindow (indirect inheritance), types that inherit from EditorWindow directly, or any unrelated type. Even a valid descendant like a subclass of GameView will fail because its BaseType is GameView, not PlayModeView.

Common situations: Custom play mode view implementations; editor extensions that try to swap to a derived window type; passing typeof(GameView) from a context where the type system resolves to a different assembly version.

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/8149e182f25532d5. Report an issue: GitHub.