Skip to content
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

Inconsistent treatment of load() from relative path #90029

Closed
Mercerenies opened this issue Mar 30, 2024 · 4 comments · Fixed by #90039
Closed

Inconsistent treatment of load() from relative path #90029

Mercerenies opened this issue Mar 30, 2024 · 4 comments · Fixed by #90039

Comments

@Mercerenies
Copy link

Tested versions

  • Reproducible in: Godot Engine v4.2.1.stable.official (b09f793)
  • Reproducible in: Godot Engine v4.02.stable.official (7a0977c)
  • Reproducible in: Godot Engine v3.5.stable.official (991bb6a)

System information

Fedora Linux 37 (Workstation Edition) - X11 - GLES3 (Compatibility) - Mesa Intel(R) UHD Graphics 620 (WHL GT2) () - Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz (8 Threads)

Issue description

Godot seems to treat relative paths in load() calls very inconsistently. From the documentation for method load,

Important: The path must be absolute. A relative path will always return null.

So I would fully expect load("./SomeScript.gd") to return null. However, it seems to do a sort of secondary load and produces a bizarre object distinct from load("res://SomeScript.gd"). See reproduction steps below.

Steps to reproduce

Define a script file called SomeScript.gd whose contents are

extends RefCounted # extends Reference on Godot 3

Then define the main scene Main.gd

extends Node2D

const SomeScript = preload("res://SomeScript.gd")

# Called when the node enters the scene tree for the first time.
func _ready():
    # These two lines print the same
    print(load("res://SomeScript.gd"))
    print(load("res://SomeScript.gd"))
    # These two lines print the same, but distinct from the above.
    print(load("./SomeScript.gd"))
    print(load("./SomeScript.gd"))

    print(SomeScript.new() is SomeScript)  # true
    print(load("res://SomeScript.gd").new() is SomeScript)  # true
    print(load("./SomeScript.gd").new() is SomeScript)  # false

Based on the documentation, I would expect the load("./SomeScript.gd") lines to return null. However, if that's not correct, then I would expect them to return the same object as load("res://SomeScript.gd"). Currently, the two different load calls return distinct and incompatible objects, which just creates confusion.

Minimal reproduction project (MRP)

LoadBug.zip

@AThousandShips
Copy link
Member

This is because of a minor issue probably, the path is converted to res://./SomeScript.gd, which is likely cached differently, can see about a fix for that part, it likely needs a normalisation of the path

The documentation should be clarified as well

@AThousandShips
Copy link
Member

The documentation should probably be updated to say instead that:
Relative paths will be prefixed with res:// and not relative to the script it is called from.

Or similar

@Mercerenies
Copy link
Author

@AThousandShips That was my first thought as well, since (during the course of debugging this issue) I noticed that Godot prints the path as res://./SomeScript.gd even if the res:// wasn't there in the load() call. But if you explicitly load res://./SomeScript.gd (with the res://), then everything actually works. You get one consistent object, and the is checks pass like they should. The problem only occurs if the res:// is missing from the load() call.

@AThousandShips
Copy link
Member

Indeed, see the linked issue, it's due to a specific path, this ensures that the loaded object is the exact same instance

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

Successfully merging a pull request may close this issue.

2 participants