Godot: `class_name`을 일부 사용하면 예기치 않게 순환 오류가 발생할 수 있습니다.

에 만든 2018년 08월 26일  ·  69코멘트  ·  출처: godotengine/godot

Windows 10 64 비트-Godot 3.1 알파

편집-주기적 오류에 초점을 맞추기 위해 문제를 수정했습니다.

class_name 의 특정 사용은 순환 참조가없는 상황에서 순환 오류를 생성 할 수 있으며 실제로 주어진 단일 참조 이외의 다른 참조가없는 경우도 있습니다.

is 를 사용하여 클래스를 비교할 때 도구 스크립트에서 가장 자주 발견되었지만 일반적인 스크립트 상황에서 가끔 발생하는 것 같습니다.

샘플 프로젝트에서 그것을 재현하는 것은 나를 피했습니다.

godot master_2018-08-27_00-47-02

bug 3.2 confirmed high priority gdscript

가장 유용한 댓글

내가 작업하고 있던 수정 사항은 여전히 ​​WIP이며 충돌을 유발합니다. 나는 베타 단계에서 그렇게 큰 변화를 병합 할 자신이 없으므로 나중에 3.2.x 릴리스에서 수행 될 것입니다.

모든 69 댓글

기본 스크립트에 class_name을 지정하고 확장 줄에서 사용하면 작동합니다.
처음에 파일 이름을 사용할 때도 오류가 발생합니다 (https://github.com/godotengine/godot/blob/master/modules/gdscript/gdscript_parser.cpp#L4947). 또한 사라지고 오지 않습니다. 한 번 작동 한 후 돌아 가기 (언급 된 해결 방법을 사용한 후)

@ PetePete1984 쿨, 고마워 피트. 이것이 어떻게 사용되는 것입니까?

이것을 두 번 확인하고 테스트하는 동안 get_class() 메서드를 살펴보고 Node2D를 반환해야하는지 궁금합니다. is CustomClass 부분은 _true_를 반환하지만 is_class("CustomClass") 는 _false_입니다.

CC @reduz @vnen @willnationsdev

나는 그것이 의도 된 행동이라고 말하지 않을 것입니다. 특히 아무것도없는 순환 포함을 암시하는 오류 메시지가 아닙니다.
get_class()is_class() 은 (는) 일반적으로 저에게 혼란 스럽습니다. 실제로 댓글을 달 수 없습니다. 소스는 장기적으로 그 수수께끼를 풀 수 있지만 지금까지는 is 로 충분했습니다.

@vnen 더 명확한 오류 메시지가 필요한 것입니까?

@ PetePete1984 예, is 는 3.1에서 놀라운 일이었습니다. match custom_thing.get_class() 와 같은 새로운 match 를 사용하고 여러 문자열과 비교하고 싶었던 상황을 발견했지만. 그러나 중요한 것은 없으며 가독성과 타이핑이 적습니다.

@avencherus 당신은 다음과 같이 도망

match custom_thing.get_script():
    <typename>: stuff # script classes
    <typename>: stuff
    _: match custom_thing.get_class():
        "Node": stuff # engine classes

이 오류가 발생하는 이유를 잘 모르겠습니다. 조사해야합니다.

@willnationsdev get_script() 부분에서 확인한 내용이 무엇인지 확실하지 않습니다. 적어도 저에게는 GDScript 개체 [GDScript:1057] 반환합니다.

@vnen 감사합니다 vnen. X) 내가 당신에게 더 나은 정보를 줄 수 있는지 알아보기 위해 이러한 제안을 시도하기 위해 돌아 갔을 때 다른 이상한 일들이 계속되는 것 같습니다. 나는 그것을 당기고 재건하고 조금 만져 볼 것입니다. 추가 할 다른 것이 있는지 확인하십시오. 나는 도중에 다른 문제에 부딪쳤을 수도 있습니다.

@avencherus 스크립트 클래스의 "클래스 이름"은 스크립트를 참조하는 전역 변수입니다. 그래서...

class_name CustomType
match get_script():
    CustomType:
        print("I am a CustomType!") # should print

@willnationsdev 오 깔끔한, 이제 볼 수 있습니다. 나는 class_name이 그렇게 작동하거나 사용자 정의 유형이 일치 패턴에 사용 가능할 것이라고 기대하지 않았습니다. 이 팁을 공유해 주셔서 감사합니다.

@vnen 예, 이야기에 추가 주름이 있습니다. 내가 그것들을 얼마나 잘 표현할 수 있는지 보자.

첫째, Pete의 솔루션이 작동합니다. 기본 클래스에 class_name 가 주어지면 모두 정상적으로 보입니다. 내가 주목 한 것은 기본 클래스로 돌아가서 내가 추가 한 class_name CustomBase 를 꺼내면 절반이 작동한다는 것입니다. 노드를 추가 할 때 더 이상 노드 목록에 나타나지 않지만 is 가 작동하고 이상한 오류가 없습니다.

그런 다음이를 확인하기 위해 base2.gd-> custom2.gd 확장 스크립트를 만드는 단계를 다시 생성했습니다. 그런 다음 custom.gd 내에서 class_name CustomClass2 를 사용하지만 기본 클래스에는 클래스 이름이 없습니다.

또 다른 문제가 나타났습니다. 노드 목록에 첫 번째 항목이 있지만 "오류"라는 아이콘과 함께 나열됩니다.

godot master_2018-08-27_20-01-26

그래서 첫 번째 기본 클래스를 수정하여 둘 다 class_name . 그러나 다시 이상한 결과를 얻었습니다.

모든 것이 노드 목록에 표시되는 것은 아니며 is 키워드는 그중 하나에 대해서만 true를 반환했습니다. 이 스크린 샷에서 노드 목록이 CustomClass2를 인식하는 것을 볼 수 있지만 그 뒤에있는 코드에서는 is CustomClass2 가 false를 반환합니다.

godot master_2018-08-27_20-05-11

많은 일이 바뀌거나 뒤에서 머무르는 것 같습니다. 제한된 지식으로 무엇을하는지 예측하기 어렵습니다.

도움이되기를 바랍니다. 엑스)

편집 이 주석을 무시하십시오. 나는 class_name 가 3.0.6에서 구현되지 않는다는 것을 깨닫지 못했습니다.이 문제는 어쨌든 3,1 빌드를 나타냅니다.

class_name 는 3.0.6에서 손상된 것 같습니다. 나는 별도의 문제를 만들 것이지만 :

image

@bfishman 스크립트 클래스는

나는 다음을 시도했고 각 버전이 작동했습니다. 모든 스크립트 클래스가 CreateDialog에 나타나고 스크립트가 제대로 컴파일되고 장면이 성공적으로 실행되었습니다.

다음과 같은 장면 계층 구조 :

  • 노드 (base.gd)

    • 노드 (derived.gd)

스크립트:

# res://base.gd
extends Node
class_name BaseNode
func _ready():
    print("base")

# res://derived.gd
extends BaseNode
extends "base.gd" # I tried both of these 'extends' lines and they each worked
class_name DerivedNode # I tried with and without this line
func _ready():
    print("derived")

테스트를 실행할 때마다 인쇄되었습니다.

base
derived
base

... 그대로.

내 제안은 편집기의 파일 캐시를 지우는 것입니다 (아마도 프로그래밍 / 엔진 업데이트 중에 파일 캐시가 저장되는 방식이 변경된 경우 지울 때까지 문제가 발생할 수 있습니다).

@willnationsdev 봐 주셔서 감사합니다. AppData / Roaming 폴더의 파일입니까? 지금은 모든 것을 정리하겠습니다. 그렇다면 삭제해야 할 더 구체적인 것이 있는지 궁금하십니까?

@avencherus 잘 모르겠습니다. 이전에 스크립트 클래스 아이콘에 몇 가지 수정 사항을 추가했을 때 @karroffel이 그것에 대해 언급 한 것을 기억합니다.

https://github.com/godotengine/godot/commit/1093c0ff51b980634dffdd9618eaa53061da6419에서 테스트되었습니다.
오류가 표시되지 않지만 "Create new Node"대화 상자에 노드가 표시되지 않습니다.

원본 게시물 (Windows x64 Godot 3.1 알파)에도 오류가 표시됩니다.

image

그러나 그것은 다른 맥락에서 발생합니다. 각각 다른 class_name 가진 3 개의 스크립트가 있으며 각각은 Node2D를 확장합니다. 스크립트 중 하나가 is 연산자로 오류를 참조하지 않으면 오류가 발생하지 않습니다. 예 : if some_var is Incomer . 하지만 이상한 점은 동일한 스크립트가 다른 class_name을 참조하는 경우 문제가 없다는 것입니다. 그리고 다른 스크립트가 문제의 class_name을 참조하면 문제 없습니다.

ClassA, ClassB, ClassC가 있습니다. ClassC가 is 연산자로 ClassA를 참조하면로드시 오류가 발생합니다. ClassC가 ClassB를 참조하는 경우 오류가 없습니다. ClassB가 ClassA를 참조하는 경우 오류가 없습니다.

동일한 장면에있는 스크립트가없고 모든 노드가 형제입니다 (조상 관계 없음).

@AlexHolly 지금도 나와 같은 상황입니다. 오류가 사라진 것 같지만 예, class_name 사용하는 기본 스크립트가 없으면 노드 추가 창에 클래스가 나타나지 않습니다.

이것은 알파 3.1 c320d93입니다.

"is"를 사용한 작은 예입니다. "as"를 사용하면 같은 일이 발생할 수 있습니다.
이것은 @Oranjoose 도 언급했습니다.
cycle.zip

동일한 장면에있는 스크립트가없고 모든 노드가 형제입니다 (조상 관계 없음).

이것은 장면의 노드와 관련이 없습니다. 주기는 스크립트 자체에서 발생합니다.

현재로서는 isas 사용할 때주기를 얻는 것이 매우 쉽습니다. 그리고 이것이 발생하면 실제로 버그가 아니라 그대로입니다. 나는 이것을 개선하려고 노력할 것이지만 3.1은 아닙니다. 코드에 실제주기가 없기 때문에 원래 보고서는 버그입니다.

451e5fd에서도 오류를 재현 할 수 없습니다. 노드가 생성 창에 표시되지 않았습니다.

0dbe014 (내가 가져온 최신 마스터)에이 문제가 없음을 확인할 수 있습니다. 이 문제를 종료 할 수 있습니다.

또한 스크립트를 확장하는 스크립트 클래스가 여전히 버그 인 CreateDialog에 표시되도록 만들 수있었습니다. PR은 위에 링크되어 있습니다.

@willnationsdev 감사합니다. X) class_name 에서 다양한 문제에 부딪 혔지만이 문제를 재현 할 수 없습니다. 그들은 재현하기가 매우 어려웠지만 그 이후로 사용을 중단했습니다.

참조되는 스크립트의 오류로 인해 때때로 모호하고 관련없는 오류가 스크립트에 나타날 수 있음을 발견했습니다. 범인 스크립트를 열 때 더 의미가 있고 수정되면 다른 스크립트도 제거됩니다.

이 주기적 오류는 여전히 이상한 상황에서 발생하는 것처럼 보이고 그것을 재현하려고 할 때 이해하기 어렵 기 때문에 게시물의 주제를 다시 조정할 것입니다. 그래서 아마 아직 뭔가가있을 겁니다. vnen을 위해 열어 두겠습니다.

@avencherus 알겠습니다 . 결국 어떤 상황에서 발생하는지 확인할 수 있기를 바랍니다. 컨텍스트 없이는 수정할 수 없습니다. XD

내 godot-next 작업에서 정적 타이핑을 사용하여 스크립트의 클래스 이름과 동일한 유형을 반환한다고 말할 수 있었던 순환 참조 오류를 발견했지만 실제로 클래스 이름을 참조하려고하면 스크립트 (나중에 함수에서 반환 할 인스턴스를 만들기 위해)의 경우 스크립트가 자체를 참조하므로 무한히 재귀 적으로로드해야하기 때문에 작동하지 않습니다.

내가 찾은 해결책은 load(get_script().resource_path).new() 입니다. 꽤 많이 알고 있지만 파서가 데이터를 안전하게 구성하고 컴파일 프로세스를 안전하게 통과하고 형식 이름을 공식적으로 등록한 다음 완전히 초기화 된 후에 만 ​​RUNTIME에 형식을 참조 할 수있게했습니다.

나는 그것을 애타게하기 위해 주기적으로 노력할 것이다. 더 많은 도움이 되길 바라지 만, 구현에 대한 깊은 지식을 가진 사람들이 자신의 프로젝트에서 작업하고 이러한 문제에 먼저 직면 할 때까지 기다려야 할 것이라고 상상하고 있습니다. 나는 그들이 그 상황에서 그들의 시각을 어디로 설정해야할지 알 것이라고 내기 할 것이다.

몇 가지 문제에 대한 간략한 요약 (다음 몇 주 내에 게시 될 예정입니다) :

  1. obj is MyClass 수행 할 때 이러한 순환 오류가 발생하고 둘 사이에 다른 연결이나 참조가 없습니다. 씬 트리를 스캔하고 그 자식을 순환 참조로 계산하는지는 모르겠지만.
  2. 나는 또한 당신이 묘사 한 불편 함을 겪었습니다. 동일한 유형의 상황에서 내장 / 네이티브 클래스 이름으로 잘 작동하기 때문에 그렇지 않았 으면합니다. 따라서 사용자 정의 유형을 추가하기 시작할 때까지이 최종 목표를 염두에두고 전체 코드를 작성할 수 있습니다. 그러면 사용자 정의 유형을 추가하기 시작할 때까지 해킹 / 해결 방법 / 이전 방법에 의존해야합니다. 자세한 경로 이름을 피하지 않으려면 그 값?
  3. 에디터에서 오류가없고 테스트 실행 중에 깨끗하게 실행했지만 내 보낸 게임에서 오류와 실패가 계속 발생합니다. 아래의 예 (이 문제와 관련이 없을 가능성이 높음)는 class_name 사용이 빌드에서 아이콘을 찾을 수 없지만 편집기의 실행 및 테스트에 문제가 없다는 것입니다.

gtc_2018-10-12_13-21-35

class_name 에 대한 전반적인 경험은 거의 매일 예측할 수없고 설명하기 어렵고 오류를 재현하기 어려운 일이 많았습니다. 주변에서 춤을 추고 해결하는 데 많은 시간이 낭비됩니다.

나는 정말로 그들을 고대하고 있었고 그들은 절대적으로 코딩을 훨씬 더 간결하고 읽기 쉽게 만들 것입니다. 실질적인 시간적 이유로 저는 그것들을 따로두고 현재 프로젝트에서 사용하지 않도록 선택해야합니다.

아마도 4.0에서. 엑스)

이전 스크립트 경로 방법으로 되돌릴 것입니다. 그렇게 할 때 임의의 class_name 놀라움을 피하고 코드를보다 일관성있게 유지하기 위해 끝까지 사용하는 것이 내 자신의 선호 사항입니다.

앞서 말했듯이, 특히 isas 사용할 때 class_name 주기를 만드는 것은 매우 쉽습니다. 경로를 사용하는 것은 쉽지 않지만 비슷한 문제에 부딪 힐 수도 있습니다. 문제는 GDScript가 그렇게 작동하도록 연결되지 않았기 때문에 리소스 로딩에 너무 많이 의존한다는 것입니다. 이 문제를 해결할 몇 가지 아이디어가 있지만 (특히 리소스로드를 무시하고 종속성을 얕게 파싱하는 경우) 파서의 구조적 변경이 필요합니다.

아마도 다음 버전에서 제대로 해결 될 것입니다. 왜냐하면 이것을 엉망으로 만들기에는 좋은시기가 아니기 때문입니다. class_name 은 (는) 당분간 "더 적은 기능"이 될 것입니다. 일부 경우에는 여전히 사용할 수 있지만 예상만큼 광범위하지는 않습니다.

@vnen 안녕하세요. 다시 오신 것을 환영합니다. 엑스)

답장과 타임 라인에 감사드립니다.

네, 그래서 지금은 그것을 선반에 넣어야합니다. 그렇게 매끄럽고 적합하거나 자연스러운 통합이 아니라는 것을 깨닫는 데 약간 느 렸습니다. (프로젝트 파일의 모든 항목을 보았을 때 일종의 힌트를 얻었습니다.)

"더 적은"기능처럼 보이지만 주름이 해결 될 수 있다면 매우 심각한 이점이있을 것입니다. 정말 기대가되며, 이미 사용해서 잃어버린 느낌이 듭니다. 확실히 GDScript를위한 좋은 길입니다.

내가 놓칠 한 가지 중요한 것은 사용자 정의 클래스가 새로운 유형 힌팅과 결합 될 때 힌트를 그릴 수있는 기능입니다. var thing : NewThing

며칠에 걸쳐 대규모 수업을 만들고 며칠 후 처음 사용하게되었을 때, 몇 번 사용하기 전까지는 모든 함수의 이름을 100 % 정확하게 기억하지 못합니다. 따라서 이러한 힌트를 얻는 것은 제게 예상치 못한 상당한 생산성 향상이었습니다. 한 지역에서 훨씬 더 오래 머물면서 일할 수있었습니다.

분명히 문제의 핵심은 쉬운 사이클이지만 가장 최악의 경험은 현재 일부 오류가 올바른 위치를 가리 키지 않는다는 것입니다. 이제 몇 주가 지났지 만 맞춤 수업을 사용하고 며칠 동안 모든 것이 잘되는 상황이있었습니다. 그런 다음 해당 사용자 정의 클래스를 호출하는 코드를 더 작성했고 개발 중 어느 시점에서주기 오류가 발생하기 시작했습니다. 어떤 경우에는 이러한 오류가 오류가 발생한 위치를 설명하는 데 도움이되지 않았습니다. 그것을 찾기 위해 나는 오류가 멈출 때까지 모든 클래스 이름 사용을 하나씩 찾아 제거해야했습니다.

그와 같은 몇 가지 사건이 많은 이익을 되찾았습니다. 나는 30,000 줄의 어딘가에서 그런 문제를 일으키는 것을 상상하는 것이 두렵습니다.

내가 그들 모두를 잡아 당기게 만든 한 가지 사건은 사이클 오류가 내보내기 빌드에서만 나타나고 관련없는 스크립트 오류를 ​​던지는 사건이었습니다. 나는 아이콘 텍스처가 발견되지 않았다고 말하는 것 같지만 실제로는 그렇지 않았으며 class_name 사용을 버리면 해결되었습니다. class_name이 실패하고 오류가 다음 줄에 떨어지는 것으로 의심됩니다.

원인 위 또는 아래 줄에서 오류가 발생하는 경우가 가끔 발생하는 것을 보았습니다.

저와 저의 제로 지식은 이러한 많은 문제의 원인을 정확히 파악하기가 정말 어렵습니다. 많은 것들이 제게는 단순히 커튼 뒤에 있으며,이 중 일부를 해독 할 수 있다는 것에 감사드립니다.

3.1에서는 경고 및 오류와 함께 비정상적인 이벤트가 많았으므로 문제가 문제 자체인지 아니면 오류보고 논리의 문제인지 궁금합니다. 아직 어디서부터 시작해야할지 정확히 알지 못합니다.이 중 일부가 도움이되고 시간이 지나면 작은 프로젝트로 좁힐 수 있기를 바랄뿐입니다.

편집 : 신경 쓰지 마세요, 어떻게 든 단순히 그것을하지 않음으로써 순환 포함을 해결했습니다 ...
project.godot 의 전역 클래스는 편집기를 시작할 때 덮어 씁니다.

@vnen 또는 @avencherus 이 버그가 무엇인지에 대한 명확한 설명으로 OP를 업데이트하는 것이 좋습니다.

@ akien-mga 나는 그 상태에 대해 더 이상 확신하지 못합니다.

내가 회상한다면 적어도 그것에 부분이 있습니다. 현재 형태의 GDScript의 한계로 예상되는 순환 오류와 소규모 프로젝트에서 분리 및 재현하기 어려운 예상치 못한 오류 (때로는 부정확 한 오류 메시지로 인해)입니다.

현재 사용중인 기능이 아니기 때문에 진행 상황을 따르지 않았습니다. 여기저기서 몇 가지 문제가 해결 된 것 같습니다.

이러한 다른 문제를 한눈에 보면 GDScript에서 필요한 변경 사항에 관한 이야기 ​​인 것처럼 보입니다. 3.2를 목표로 한 개정으로. 그것이 계획이라면 더 이상 3.1 이정표 아래에 있지 않을 것입니다.

vnen이 부기 용으로 사용하지 않거나 3.1.0이 안정 될 때 다가오는 중복 문제를 참조하기 위해 사용하는 것을 선호하지 않는 한 이것을 닫는 것이 좋습니다.

이 기능은 제가 관심을 갖고있는 유용성 측면에서, 3.2에서 다시 방문하여 결과를 게시 할 것입니다.

글쎄, 이것은 닫히지 않아야합니다. 아니요, 많은 양의 중복 보고서가 수정해야 할 것이 있음을 분명히 보여줍니다. :)

3.0에서 3.1로 프로젝트를 업데이트하는 데 문제가되는 다음 오류 메시지가 나타납니다. 이전에는 다음 코드가 작동했습니다.

extends Node2D
export(String, FILE, "*.gd") var _class_name = "res://Test.gd"
onready var SomeClass = load(_class_name)

func foo():
    for c in get_children() :
        if c is SomeClass : 
            do_stuff()

코드를 다음과 같이 변경할 때 :

extends Node2D
class_name SomeClass

func foo():
    for c in get_children() :
        if c is SomeClass : 
            pass

다음과 같은 오류가 발생합니다.

구문 분석 오류 : 클래스 파일에서 하나의 이름을 사용할 수 없습니다 (순환 참조 생성).

내가 찾고있는 자식 노드가 모두이 클래스에서 상속하고 그렇지 않은 다른 자식 노드와 혼합되어 있기 때문에 이것은 나에게 실망 스럽습니다. 이런 식으로 작동하지 않도록 의도 된 스크립트 클래스의 다른 인스턴스에 대해 유형 검사를 수행 할 수 있는지 여부와이 작업을 수행해야하는 다른 방법이 있습니까?

@Diaspater if c is SomeClassif c is get_script() 로 변경하는 것 뿐이라고 생각합니다. 두 옵션 모두 런타임 검사를 실행하지만 SomeClass 버전에서는 get_script() 메서드가 어떤 작업도 수행하지 않는 동안 편집기 타임에 스크립트를 다시로드해야합니다 (순환 참조 결과). 편집자 시간.

@willnationsdev 나는 그것이 유효한 해결책

DummySomeClass.gd
extends Node2D
class_name DummySomeClass

func foo():
    pass


SomeClass.gd
extends DummySomeClass
class_name SomeClass

func foo():
    for c in get_children() : 
        if c is DummySomeClass: 
            pass

즉, 현재 오류가 발생하는 이유에 대한 설명을 이해합니다. 이 문제에 대한 여러 솔루션 또는 해결 방법을 사용하면 이것이 수정해야 할 필수적인 버그는 아니지만 향후 어느 시점에서 수정되기를 바라는 버그라고 생각합니다.

이 방법을 약간 더 복잡한 용도로 사용한 후에는 다른 결합 스크립트의 다른 위치에서 다른 순환 오류가 발생하는 것으로 보이므로 문제에 대한 좋은 해결책 / 해결 방법이 아닐 수 있습니다.

이것은 순진한 질문 일 수 있지만이 비순환 적 제한을 제거해서는 안됩니다.
Java, C #, C ++ 등과 같은 다른 언어는 문제없이 유형을 처리 할 수 ​​있습니다.

@harraps 가 완료되지만 (쓰레드에서 몇 번 언급했듯이) GDScript가 연결되는 방식에 근본적인 변경이 필요합니다. 릴리스가 가까워지고이 변경으로 호환성이 깨질 가능성이 있으므로 지금은 다루지 않겠습니다.

다른 사람이이 문제가 발생하는 경우 "순환 참조"관련 오류의 다른 인스턴스를 찾았지만 여기에 나열된 다른 오류와 다릅니다.

반환 값에서 현재 클래스의 이름을 참조하는 정적 팩토리 메서드로 클래스를 만들면 편집기 자체 내에서 어떤 종류의 오류도보고되지 않지만 편집기가 닫히면 오류보고를 받게됩니다. 리소스가 여전히 사용되고 있습니다.

extends Reference
class_name MyClass

static func make() -> MyClass:
    # can't even use get_script() for static funcs, but that's a separate issue
    var c = load("res://my_class.gd").new()
    return c

그런 다음이 오류가 발생합니다.

ERROR: SelfList<class GDScriptFunction>::List::~List: Condition ' _first != 0 ' is true.
   At: .......\godot\core/self_list.h:111
ERROR: SelfList<class GDScript>::List::~List: Condition ' _first != 0 ' is true.
   At: .......\godot\core/self_list.h:111
WARNING: ObjectDB::cleanup: ObjectDB Instances still exist!
     At: core\object.cpp:2093
Leaked instance: GDScript:17060 - Resource name:  Path: res://my_class.gd
Leaked instance: GDScriptNativeClass:1058
ERROR: ResourceCache::clear: Resources Still in use at Exit!
   At: core\resource.cpp:425

# 944에서 다시 게시,

나는 또한 주기적으로 GDscript 종속성을 정기적으로 실행하고 있습니다. 다음은 현재 유형이 지정되지 않은 GDscript로 되돌려 야하는 몇 가지 사용 사례입니다.

  1. 내 캐릭터는 다른 Move 를 실행하는 ActorController 를 사용합니다 (상태 머신의 상태와 같이). ActorController_physics_process() 등을 활성 Move 합니다. 반대로 이동은 ActorController 에 액세스하여 다른 Move 하거나 속성 (예 : 점프 높이, 달리기 속도 등)에 액세스합니다.

  2. MoveRepository 와 동일한 상황-저장소는 재사용 가능한 Move 저장하지만 Move 는 다른 Move 를 가져 오려면 저장소에 액세스해야합니다. ActorController 로 선택합니다.

actor-framework

이것은 C # 또는 C ++에서 문제가되지 않지만 GDscript (선택적 정적 입력 사용)를 사용하려면 변형 (동적 입력)으로 돌아가거나 이벤트 등을 사용하여 불필요한 간접 지정을 만들어야합니다.

나는 또한이 문제가 있습니다. 비슷하지만 더 간단한 설정이 있습니다.
TurnManager 클래스에는 Actor 유형의 변수가 있으며 모든 Actor 에는 TurnManager 대한 유형화 된 참조가 있습니다.
나는 is 사용하지도 않고, 문자 그대로 변수를 선언했고이 오류를 유발하기에 충분합니다.
Linux 64 비트에서 새로운 안정 버전 3.1 사용.

image

방금 만났어요. 관련이있는 것 같습니다.

image

참으로 매우 이상합니다.

image

나도 이런 일을 겪고있는 것 같다. 스크립트가 대부분 객체에서 분리 되었기 때문인지 궁금합니다. 노드를 확장하는 기본 Attribute 클래스와이를 확장하는 PrimaryAttribute 및 SecondaryAttribute, 그리고 12 개의 PrimaryAttribute 노드와 SecondaryAttribute 노드가 있습니다. 편집자가 좋아하지 않는 것 같나요? 내가 할 때 게임이 잘 실행되지만.

참고로, 나는 class_names에 대한 리소스 경로를 전환했으며, 이유없이 오류가 발생하기 전에 약 5 분 동안 제대로 작동했습니다. : /

흠. 오류가 편집기 창에로드되는 순서와 관련이있는 것 같습니다. 상속 된 순서대로 파일을 닫고 다시 열면 파일이 사라지도록 할 수 있습니다. 따라서 일부 파일에서 선언하지 않는 문제가있을 수 있습니다. : /

편집 : 실제로 아니요, 파일을 여는 순서는 중요하지 않습니다. 다른 파일이 열려 있더라도 상관 없습니다. 이 파일 중 하나를 처음로드하면 오류가 표시되지 않고 변경 될 때까지 표시되지 않고 모든 오류가 표시됩니다. : /

@ Angular-Angel Godot를 다시 시작하면 오류가 해결되는 것으로 나타났습니다. Godot에서 커스텀 클래스 / 타입으로 정적 타이핑을 아직 사용할 수 없다는 것은 실망 스럽습니다.

프로젝트를 "그냥"닫거나 다시 여는 것만으로도 충분했습니다. Shift + Ctrl + Q (프로젝트 목록으로 이동), 프롬프트를 확인한 다음 프로젝트를 다시 두 번 클릭합니다. 여전히 약간 실망 스럽지만 익숙해집니다 (고정 될 때까지).

미안하지만 저도 약간 실망하고 여러분이 언급 한 이후로 그 해결 방법에 대해 몰랐습니다. 잠시 동안 코드 입력을 중단했지만 여전히 많이 그립습니다.

동의합니다. 이것은 나 자신과 다른 사람들에게 매우 빠른 습관이되었습니다. 다시 시작 해결 방법이 당분간 충분한 지 확인할 수 있습니다. (빨리 시작하는 Godot이 좋을 것입니다) 2019 년 5 월 16 일 오전 8시 27 분에 Ricardo Alcantara [email protected] 은 다음과 같이 썼습니다. , 나는 잠시 내 코드 입력을 중단했지만 여전히 많이 그리워합니다.

— 댓글을 달았 기 때문에 전송 된 것입니다.이 이메일에 직접 답장하거나 GitHub에서 보거나 대화 목록을 음소거하세요.

Godot 3.1.1 (모노 아님)
Stack.zip

재현 가능한 최소한의 예

https://cdn.discordapp.com/attachments/477544613511692358/584811385838632977/unknown.png

_ 제발 _ 누군가 고쳐주세요.

image

로드는 잘 작동하지만 미리로드는 작동하지 않습니다.

실제로 StackList.gd에는 포착되지 않은 스크립트 오류가 있습니다. 특히 사전 키 선언의 구문 오류입니다. 그러나 사전이 상수로 변경된 후에 만 ​​포착됩니다.

오늘도 "is"class_name 버그가 발생했음을 기록하고 싶었습니다.

object가 className인지 테스트하는 대신 object.has_method ( "name") 사용으로 되돌 렸습니다.

나는 이것을 3.1.1에서 자주 치고, 그것을 피하기 위해 농구를 뛰어 넘었습니다.
3.2에서 수정되기를 바랍니다!

새로운 정보없이 문제가 발생하지 않도록 부탁드립니다. 우리 모두는 이런 일이 발생한다는 것을 알고 있으며 이미 많은 예제를 가지고 있으며 더 많은 의견으로 마술처럼 사라지지 않을 것입니다.

나는 현재 @JavaryGames 에서이 문제를 해결하려고 노력하고 있으며 솔루션은 이미 진행 중입니다. 큰 변화이고 (GDScript가 내부적으로 작동하는 방식을 다소 변경해야했기 때문에) 3.2로 만들지는 확실하지 않지만 출시에 가까워졌지만 3.2.1 또는 그 이상으로 통합 할 수 있습니다. 4.0에서 확실히 수정 될 것입니다.

내가 작업하고 있던 수정 사항은 여전히 ​​WIP이며 충돌을 유발합니다. 나는 베타 단계에서 그렇게 큰 변화를 병합 할 자신이 없으므로 나중에 3.2.x 릴리스에서 수행 될 것입니다.

@vnen 이 버그를 수정하고 컴파일하고 테스트 할 수있는 브랜치가 있습니까?

이 시점에서 자세한 정보가 도움이되는지 확실하지 않지만 해결 방법은 문제가있는 클래스의 class_name 를 변경 한 다음 다시 변경하는 것입니다. 캐시와 관련된 것처럼 보입니다.

변수가 캐스팅 된 클래스의 메서드 시그니처를 변경 한 직후 as 사용하여 클래스 멤버를 캐스팅하는 줄에서 발생했지만 실제 메서드를 수정하기 전에 발생했습니다. 그런 다음 메서드를 수정 한 후 줄에서 계속이 오류가 발생했으며 마침내 캐스트 클래스의 이름을 다른 것으로 변경 한 다음 다시 변경했을 때만 중단되었습니다.

@vnen 이 버그를 수정하고 컴파일하고 테스트 할 수있는 브랜치가 있습니까?

예, 공개 포크에 있습니다 : https://github.com/vnen/godot/commits/gdscript-no-cycles

이 시점에서 자세한 정보가 도움이되는지 확실하지 않지만 해결 방법은 문제가있는 클래스의 class_name 를 변경 한 다음 다시 변경하는 것입니다. 캐시와 관련된 것처럼 보입니다.

편집하는 동안 모든 항목이 항상 다시로드되므로 편집기에서 일부 캐싱 아티팩트를 얻을 수 있습니다. 그러나이 문제에 도달하면 편집기에서 오류가 발생하지 않더라도 실행할 때 작동하지 않을 가능성이 큽니다.

https://github.com/godotengine/godot/issues/38265 는 일부 복제 세부 정보가 포함 된 중복 보고서 인 것으로 보입니다.

이 수정 사항이 언제 메인 라인에 올까요?
유형 저장 스크립트를 사용 하고이 문제에 자주 실행되기 때문에 매우 짜증납니다.
오늘 나는 해결할 수없는 상황에 처한다.

extends Resource
class_name WfcSlotHistory

func _init(slot:WfcSlot):
    pass
extends Resource
class_name WfcSlot

function saveHistory():
   var history:WfcSlotHistory = WfcSlotHistory.new(self)
   ...

res : //assets/wfc/WfcSlotHistory.gd : 5-구문 분석 오류 : "WfcSlot"클래스를 완전히로드 할 수 없습니다 (스크립트 오류 또는 순환 종속성).
모듈 / gdscript / gdscript. cpp : 576- 메서드가 실패했습니다. 반환 : ERR_PARSE_ERROR

@MikeSchulze 이 경우 부분적으로 디자인 문제인 것 같습니다. WfcSlot 는 아마도 WfcSlotHistory 대해 모를 것입니다. save 작업은 아마도 후자에있을 것입니다.

(이 행동 / 버그 _is_ 짜증나지만, 오해하지 마십시오.)

@ Jeto143 귀하의 응답에 감사드립니다. 모든 슬롯 멤버를 수동으로 SlotHistory에 복사하여 문제를 해결했습니다.
이 버그가 해결되기를 바랍니다.

이 길고 긴 버그가 마침내 해결 될 때 개발자 여러분 안녕하세요?

처음에는 클래스에 여러 생성자가 필요하지만 허용되지 않는 이유는 무엇입니까?
두 번째로이 문제를 해결하기 위해 정적 함수를 사용하려고하지만 이것도 작동하지 않습니다.

나는 이와 같은 수업이 있습니다 (simpe 예제)
````
자원 확장
class_name ClassA

_init (valueA : int, valueB : int) :
prints (valueA, valueB)

(value : int)-> ClassA의 정적 기능 :
반환 ClassA.new (값, 값)
````

````
var o : ClassA = ClassA.new (1,2) # 잘 작동합니다.

var o2 : ClassA = ClassA.of (2) # 오류 발생

````

정적 함수를 사용하면이 오류가 발생합니다.
"파서 오류 : 클래스 파일에서 자신의 이름을 사용할 수 없습니다 (순환 참조 생성)."

그래서 이것은 현대 언어에서 표준 동작 인 여러 생성자를 사용하는 클래스를 작성하는 것을 방해합니다.

나는 이와 같은 현재의 해키 해결 방법을 사용합니다.
```
정적 기능 of (value : int)-> ClassA :
var clazz = load ( "res : //../../ClassA.gd")
반환 clazz.new (값, 값)
````

친애하는
마이크

이 길고 긴 버그가 마침내 해결 될 때 개발자 여러분 안녕하세요?

GDScript 재 작성의 일부로 4.0에서 해결 될 것입니다.

고정 된 경우 정적 함수에서도 작동합니까?

class_name Cls

static func f():
    print(Cls)

@vnen 그래서 우리는 3.2.X 릴리스에 있습니다. 조만간 수정을 기대할 수 있습니까?

@ Ploppy3 이러한 수정 사항은 GDScript 재 작성과 함께 제공되는 대규모 변경 사항으로 인한 것이며 체리 선택이 불가능할 가능성이 높습니다. 이러한 수정 사항을 사용하려면 4.0으로 업그레이드해야합니다.

이 문제도 여기에 두 가지 스크립트가 있습니다.

class_name Entity extends Area2D

export var resource : Resource

onready var sprite   = get_node("sprite")
onready var collider = get_node("collider")

func _process(delta: float) -> void:
    if sprite   == null: sprite   = get_node("sprite")
    if collider == null: collider = get_node("collider")
    if resource is EntityConfig:
        sprite.frame = wrapf(sprite.frame+resource.gfx_speed, resource.gfx_start, resource.gfx_start+resource.gfx_count)
class_name EntityConfig extends Resource

export var gfx_image   := ""
export var gfx_start   := 0
export var gfx_speed   := 1.0
export var gfx_count   := 0
export var gfx_xoffset := 0.0
export var gfx_yoffset := 0.0
export var gfx_xsize   := 16.0
export var gfx_ysize   := 16.0
export var hit_xoffset := 0.0
export var hit_yoffset := 0.0
export var hit_xsize   := 16.0
export var hit_ysize   := 16.0

func new()->Area2D:
    var entity = Entity.new()
    entity.sprite            = Content.load_texture(gfx_image)
    if entity.sprite != null:
        entity.sprite.frame      = gfx_start
        entity.sprite.position.x = gfx_xoffset
        entity.sprite.position.y = gfx_yoffset
        entity.sprite.hframes    = entity.sprite.texture.get_width () / gfx_xsize
        entity.sprite.vframes    = entity.sprite.texture.get_height() / gfx_ysize

    entity.collider.position.x      = hit_xoffset
    entity.collider.position.y      = hit_yoffset
    entity.collider.shape.extents.x = hit_xsize / 2
    entity.collider.shape.extents.y = hit_ysize / 2
    return entity

Godot 3.2.3에서 캡 스톤 그룹 프로젝트를 진행하면서이 문제를 발견했습니다. 충돌 콜백의 경우 다음과 같습니다.

extends Area2D

func _on_Throwable_body_entered(body: Node) -> void:
    if body is Player:
        if body.pick_up():
            queue_free()

따라서 플레이어 별 메서드를 호출하기 전에 if body is Player 를 확인하고 싶습니다. 문제는 class_name 또는 preload -ed를 통해 선언되었는지 여부에 관계없이 전역 범위에 있더라도 Player 사용할 수 있거나 사용할 수 없다는 것입니다. 이것은 Player 가 명백한 순환 종속성을 유발하기 위해 스크립트를 미리로드하지 않는 경우에도 발생합니다.

우리는 현재 PlayerArea2D 의 충돌 마스크에서 유일한 것임을 확인하고 코드에서 아무것도 확인하지 않음으로써이 문제를 해결하고 있습니다. 처음에는 if body.name == "player" .

시간이 오래 걸리더라도 작업이 진행되고 있다는 사실을 알게되어 기쁩니다. 모든 것이 잘되기를 바랍니다.

정적 메서드를 사용하여 Builder 패턴을 구현하지 못하게했을 때 비슷한 종속성 문제가있었습니다.

class_name MyClass

static func build() -> MyClass:
  var new_instance  = MyClass.new()
  ...
  return new_instance

소스 파일 경로에서 클래스를로드하기 위해 여기 에 설명 된 해결 방법은 좋지만 소스 코드를 변경하지 않고 파일 트리를 변경하지 않아야합니다.

이 트릭을 사용하여 정적 메서드 (get_script ()를 사용할 수 없음)에서도 현재 소스 파일 경로를 사용합니다.

static func build() :
    var new_instance = load(GodotExt.current_script_path()).new()
    ...
    return new_instance

class_name GodotExt

static func current_script_path():
    return get_stack()[1].source    <- return usable script path

현재 수업을 얻는이 트릭은 어디서나 작동하는 것 같습니다.
원시이며 전역 종속성 수정을 기다리는 유사한 순환 종속성 문제를 방지하는 데 사용할 수 있습니다.

안녕하세요 @AliBouarab 좋은 트릭

이 페이지가 도움이 되었나요?
0 / 5 - 0 등급