Skip to content

Use 3D related nodes in editor causes runtime issue with disable_3d = true export template #103315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Delsin-Yu opened this issue Feb 26, 2025 · 5 comments

Comments

@Delsin-Yu
Copy link
Contributor

Delsin-Yu commented Feb 26, 2025

Tested versions

Current master [01545c9]

System information

Godot v4.4.rc.mono (01545c9) - Windows 10 (build 19044) - Multi-window, 4 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 4060 Ti (NVIDIA; 32.0.15.7242) - AMD Ryzen 9 5900X 12-Core Processor (24 threads)

Issue description

As disable_3d won't work with editor builds, developers, must use an editor with 3d enabled (for generating C# bindings and development), leading to usability problems for GDScript and C#.

For GDScript, scripts that directly reference 3D nodes or nodes' 3D related properties will cause runtime Parse Error:

func _ready() -> void:
	var node3d = Node3D.new();
	add_child(node3d);
SCRIPT ERROR: Parse Error: Identifier "Node3D" not declared in the current scope.
          at: GDScript::reload (res://rotategd.gd:4)
ERROR: Failed to load script "res://rotategd.gd" with error "Parse error".
   at: ResourceFormatLoaderGDScript::load (modules\gdscript\gdscript.cpp:3022)

For C#, scripts that directly instantiates or loads the 3D related binding types will cause TypeInitializationException:

public override void _Ready()
{
    var viewport = GetViewport();
    GD.Print(viewport.OwnWorld3D);
}
ERROR: System.TypeInitializationException: The type initializer for 'Godot.Viewport' threw an exception.
 ---> Godot.GodotObject+NativeMethodBindNotFoundException: Unable to find the native method bind. (Method 'Viewport.set_world_3d')
   at Godot.GodotObject.ClassDB_get_method_with_compatibility(StringName type, StringName method, UInt64 hash)
   at Godot.Viewport..cctor()
   --- End of inner exception stack trace ---
   at Godot.Viewport.IsUsingOwnWorld3D()
   at Godot.Viewport.get_OwnWorld3D()
   at Rotate._Ready()
   at Godot.Node.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret)
   at Godot.CanvasItem.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret)
   at Godot.Node2D.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret)
   at Rotate.InvokeGodotClassMethod(godot_string_name& method, NativeVariantPtrArgs args, godot_variant& ret)
   at Godot.Bridge.CSharpInstanceBridge.Call(IntPtr godotObjectGCHandle, godot_string_name* method, godot_variant** args, Int32 argCount, godot_variant_call_error* refCallError, godot_variant* ret)
   at: void Godot.NativeInterop.ExceptionUtils.LogException(System.Exception) (:0)

Steps to reproduce

  1. Compilte the Godot Editor with mono_enabled:
    scons p=windows module_mono_enabled=yes compiledb=yes debug_symbols=yes
  2. Generate the mono glue:
    .\bin\godot.windows.editor.x86_64.mono.console.exe --headless --generate-mono-glue modules\mono\glue
  3. Build the C# SDK:
    python .\modules\mono\build_scripts\build_assemblies.py --godot-output-dir=.\bin
  4. Build the export template with mono_enabled & disable_3d
    scons p=windows module_mono_enabled=yes debug_symbols=yes target=template_release arch=x86_64 disable_3d=yes
  5. Reproduction:
    a. For GDScript, create a project with GDScript that directly references 3D types (Node3D, etc.).
    b. For C#, create a project with C# script that directly or indirectly references 3D types (Node3D, Viewport, etc.).
    c. Alternatively, open the MRP Project.
  6. Export the project with the built export template.
  7. Run the exported project and observe the issue.

Minimal reproduction project (MRP)

Test2dProject.zip

@Delsin-Yu
Copy link
Contributor Author

The best solution for this issue is to enable disable_3d for editor builds; however, this requires an experienced engine developer to implement.

@akien-mga
Copy link
Member

Disabling all 3D functionality in the editor would require a lot of boilerplate and bloat, I'm not sure it can be done reasonably.

The expectation here is that if you compile a template with disable_3d (advanced use case), you should make sure not to use 3D nodes. If you do, and your export fails running, then it should at least make it clear where you need to modify your code/scenes to support disable_3d. The UX isn't great, but I'm not sure it can be made much better without a lot of hassle.

Editor Feature Profiles can help to some extent, as you can disable the 3D Editor, and Node3D. I don't think this would actually raise errors if you do use Node3D-derived nodes in your scenes added before setting the feature profile, but that should help prevent adding new ones. That doesn't restrict which nodes are available from scripts on the other hand, and addons from the asset library could still add 3D nodes. But I think it's a good first step.

So my suggestion would be to document the use of feature profiles for users who want to use export templates with disable_3d. And maybe add a pre-defined disable_3d feature profile that disables "3D Editor", "Node3D", and maybe some other 3D workflow related resources like Shape3D, Occluder3D, etc.

@Delsin-Yu
Copy link
Contributor Author

You are correct; I'm already using a 2D profile for my project.
The issue concerns the usability of scripts, more precisely, the Compilation-time safety checks for the types and properties.

2D.zip

@Delsin-Yu
Copy link
Contributor Author

Since disable_3d cannot be enabled for editor builds, is it possible to create an alias called disable_3d_editor specifically for editor builds? This would implement an editor-only GDScript parser and C# binding generator logic to handle the disabling of 3D-related nodes (so that the 3D is still enabled Engine-wise but cannot be accessed by the user scripts except through ClassDb).

@Delsin-Yu
Copy link
Contributor Author

On top of / apart from that, the GDScript parser and C# binding generator can be modified to accept the feature profile and disable extra types based on that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants