これはより非公式なトピックですが、Godotの主要な問題ではないにしても劇的な問題です。
Godotエンジンの開発者が、それを使用するユーザーをどのように計画したかは誰にもわかりません。
関連する問題:#19486#7402#15996#8502
これらはトップ4ですが、同じ問題を解決することを目的とした類似したものがたくさんあります。誰もが使用可能なワークフローを探しています。
驚くべきことに、Godotユーザーは、他の使い慣れたエンジンをコピーする非効率的なワークフローを作成することができました。 これを実証するために、Godotで作成された場合のMeshInstanceのモッククラスを使用します。
疑似Unity、別名子ノードがあります:
Godotユーザーは、子ノードを使用してMultiScriptに相当するものを作成します。
MeshInstance(Spatail + script)
---メッシュ(メッシュ+スクリプト)
---マテリアル(ノード+スクリプト)-シェーダー(ノード+スクリプト)-テクスチャ(ノード+スクリプト)
---変換(Position3D + script)
基本的に、彼らは最も適切なノードを使用し、スクリプトを使用して必要なクラスを作成するために必要なものをコーディングします。
問題:
1.)これは沸騰した鍋に冷水を加えるのとデジタル的に同等です。 短期的には役立ちますが、大規模なプロジェクトではさらに混乱を招きます。
2.)ほとんどのユーザーは、イベントなどのシグナルを使用し、それらを送信するノードにのみ接続し、エクスポートを使用してターゲットを見つけることになります。
3.)イベントは、下位ノードに到達する前にインターセプトできます。
4.)パフォーマンスが遅く、約50000オブジェクトで、ゲームがシーンを読み込もうとするとストールする可能性があります。疑似アンリアル、別名コントローラーおよび中間:
Godotユーザーは、すべての子を操作するコントローラーと所有者ノードを作成します。 このワークフローのトレードマークは、extendsで派生したクラスです。
MeshWithTexturedMaterial.instanced()*ツリー内のノードのみ
->から拡張-> MaterialTextured->から拡張->マテリアル->から拡張->シェーダー
このシステムでは、重いプレーニングが必要です。そうしないと、多くのクラスで同様のコードになってしまいます。 カメラのように、キャラクターと車両のクラスにはすべて、「フォローターゲット」の独自のコピーが含まれています
問題:
1.)デバッグが面倒な厄介な大きなスクリプト。
2.)異なるクラスでコードを複製します。
3.)Godotはノードをクラスとして扱いません。 これらの開発者に、自己コード化されたクラスを頻繁に中継するように強制します。
4。)_ combat system_が_weaponsystem_を拡張し、最後にプレーヤーを拡張するように、拡張は意味がありません。疑似Panda3D、別名Preload(スクリプト):
これは、ほとんどのコードベースのエンジンがどのように機能するかのワークフローを複製したものです。 多くの場合、開発者はノードよりも多くのスクリプトを使用します。
MeshInstance(ノード)
プリロード(メッシュスクリプト)
プリロード(マテリアルスクリプト)
プリロード(変換スクリプト)
不思議なことに、C#がこのアプローチに明らかに優れている場合でも、GDscriptを放棄することを拒否するのはこれらの開発者です。 だから私は彼らがPythonに精通していると思います。
問題:
1.)定数はonreadyの変数である可能性があるため、インポートの呼び出し方法に関する混乱。 知るか。
2.)Godotノードを使用することはめったにありません。開発者がUIツールを完全に無視しているのを見たこともあります。
3.)スクリプトがリンクされている場所が示されていないため、デバッグに苦労します。WTFスクリプト:
最後にベストを残しました。 一部のGodotゲーム開発者は、SignalsとGroupsを使用して優れたゲームを作成することができました。
上部に空のノードがあるMeshInstance(Node)を使用すると、子を簡単に移動して再設計できます。
---メッシュ(メッシュ+スクリプト||信号)
---マテリアル(スプライト+スクリプト||シグナル)
---変換(Position3D + Script || Signal)
ツリーが2シーン以上の深さのオブジェクトを接続する必要がある場合は、代わりにグループが使用されます。 このワークフローで注目に値するのは、浅い木があることです。
問題:
1.)シグナルとグループを使用すると、警告なしでゲームのすべての部分を失敗させることができます。
2.)ただうろついている小さな無意味なスクリプト。 彼らがするのは、信号を送信し、単一の値を追跡することだけです。
3.)非常に多くの信号が接続されているオブジェクトを移動することは、少なくともイライラします。
4.)インスタンスシステムとの競合。 なぜなら、信号が最も上向きに接続している間、インスタンスは下向きに流れるからです。
はい、GodotにMeshInstanceクラスがあることは知っています。
これが示すポイントは、現在開発者が使用しているワークフローのほとんどは、マルチコンポーネントを備えたMeshInstanceと同じくらい複雑なクラスを作成できるということです。 ただし、各ワークフローに重大な欠陥があります。
これらすべてのワークフローは、同じコア問題を共有しています。 これらは、ゲームを開発するための短期的なソリューションです。
それらのどれもうまくスケーリングせず、デバッグはそれらすべてに欠陥があります。
Godotゲーム開発者がエンジン開発者に必要としているのは、複雑なオブジェクトやシステムを作成するための公式ワークフローを明らかに減速することです。
そうすれば、彼らは逸脱しますが、それがどのように使用されることを意図していたかを常に知っています。
質問が単純に「Godotで同じ結果を達成する方法はいくつかありますか?」である場合、答えは「はい」です。 また、ゲーム内の各システムには異なる要件がある可能性があるため、単一のワークフローを強制しようとするのはばかげています。 多くのパフォーマンスを必要とし、ゲームデザイナーが頻繁に更新する必要があるシステムと同じ方法でコーディングすることはできません。 すべてのソリューションにはトレードオフがあるため、「公式」ワークフローを作成する意味はありません。
複数のコンポーネントを持つMeshInstanceと同じくらい複雑なクラスを作成できます
正確にはどのコンポーネントで?
編集:そしてあなたが引用した問題の1つは、著者が「このアイデアは本当にそして完全にひどく、完全に無意味である」と述べて締めくくられました。
これを実証するために、Godotで作成された場合のMeshInstanceのモッククラスを使用します。
疑似Unity、別名子ノードがあります:
Godotユーザーは、子ノードを使用してMultiScriptに相当するものを作成します。
疑似アンリアル、別名コントローラーおよび中間:
疑似Panda3D、別名Preload(スクリプト):
WTFスクリプト:
はい、GodotにMeshInstanceクラスがあることは知っています。
これが示すポイントは、現在開発者が使用しているワークフローのほとんどは、マルチコンポーネントを備えたMeshInstanceと同じくらい複雑なクラスを作成できるということです。 ただし、各ワークフローに重大な欠陥があります。
あなたがここで何を言おうとしているのかよくわかりません。 すでにMeshInstanceクラスが存在するのに、なぜ誰かがMeshInstanceクラスを作成するのでしょうか。 そして、Godotが他のエンジンと同様の機能を備えているのはなぜ問題なのですか? また、1つのノードに複数のスクリプトをアタッチしようとしている場合は、OOPを使用しないか、2つの別個の機能を1つのノードに配置します。これは、Godotのノードシステムを使用して簡単に修正できます。
質問が単純な場合:「Godotで同じ結果を達成する方法はいくつかありますか?」、答えは「はい」です...
ハンマーを作ると、それが何を意味するのかがわかります。使用できるものがすべてわからなくても、使用してはいけないものがいくつかあります。
それが何であるかわからない人にハンマーを与え、それを使用する方法を説明したことがない場合。 彼らが激しく揺れ始めたとき、あなたは驚いて行動することはできません。
これはGodotがいる場所であり、開発者は暗闇の中で揺れ動いており、どういうわけかこれによって何かを作成できるようになることを望んでいます。
正確にはどのコンポーネントで?
マテリアルやトランスフォームのようなものは、元のインスタンスの一部と見なされますか?
同様のコンポーネントを作成する場合、それらをノードにどのようにアタッチしますか?
「ターゲットをフォローする」や「ターゲットを撃つ」などの他のタスクは、クラスに追加するか、何らかの方法で添付する必要がありますか?
GodotがGodotの適切なインクルードまたはインポート機能を作成したことはないので、それはそれがそのように使用されることを意図されていなかったことを意味しますか?
私たちはすべてを手に入れることはできないことを知っているので、問題は私たちが何を持っているかということです。 動作するように設計されましたか?
@MysteryGMゆるくて切り離されたアナロジーは役に立ちません。
材料や変形のようなもの
TransformはSpatialプロパティであり、MaterialsはMeshプロパティです。 MeshInstanceはSpatialの上に構築されているため、Spatialのすべてのプロパティを継承します。 それは私にとって理にかなっている単純な階層です。
同様のコンポーネントを作成する場合、それらをノードにどのようにアタッチしますか?
Godotがすでにメッシュシステムを持っているのに、なぜ独自のメッシュシステムを作成するのでしょうか。
「ターゲットを追跡する」や「ターゲットを撃つ」などの他のタスクはどうですか
コードはスクリプトに含まれます。 それをノードのメインスクリプトに配置するか、そのようにする方が便利だと思われる場合は、スクリプトを使用して子を与えることができます。
Godotがすでにメッシュシステムを持っているのに、なぜ独自のメッシュシステムを作成するのでしょうか。
ゲームオブジェクトはメッシュと同じくらい複雑なので、もっと注意してください。 ゲームの一部がオリジナルであったエンジンは、再利用された部分にすぎなかったことを思い出してください。
Godotがエンジン内にMeshクラスを効果的に作成できない場合、複雑なゲームを作成するために使用することはできません。 すべてのゲームは、エンジンよりも複雑である必要があります。
これは、プロの開発者チームには役に立たないことを意味します。 そのようなチームがソースコードでC ++のみを使用しない限り。
コードはスクリプトに含まれます。
しかし、どのように?
100万を超える関数が必要になり、100万の空のノードでさえ、Godotには多すぎるため、すべてのスクリプトで子を作成できないことはすでにわかっています。
それはどういう意味ですか、いくつの関数をグループ化する必要がありますか、それとも紙にオブジェクトの継承を計画するために2〜4か月を費やす必要がありますか?
私が知りたいのは、Godotが、気象効果、体積霧、大きな地形などの複雑なシステムを備えた大規模なゲームをどのように処理するかということです。
以下は私、私の意見と経験、_YMMV_に関連しています
すべてのエンジンには癖があり、Godotも例外ではありません。 私が正直に言うと、最初の安定したリリースからどれくらいの時間が経過したかを考えると、それがどれほど優れていて、どれほど速く進化したかについては間違いなくうんざりしています。 それが私たちが抱えている問題のいくつかの理由かもしれません。 シーン/ノードシステムは私のお気に入りの部分です。スクリプト化されたノードのシンプルさが私にとって本当に輝いています。 私には欠点がありますが、Pythonのような構文は嫌いです...そしてプリロードシステムは... C#を機能させる方法を理解できませんでした。
Unity 4/5を例にとると(私は何年にもわたってチェーンされていました)、これまでに使用した他のECSと比較できないほど肥大化した_components_があります。 そして、ああ、あなたはhttpリクエストをしたいですか? もちろん、シーン構造の新しいオブジェクトに新しいコンポーネントを追加します。これは、httpリクエストをシーン内のオブジェクトとそのコンポーネントと結合することが非常に理にかなっているためです。 「変更なしでシーンを保存するとすべてのUUIDが壊れる」機能は、技術者以外の設計者がバージョン管理を使用しにくくするためだけに作成されたようです。 「ロード時に破壊しないでください」とプレハブを始めたくありません。
とにかく、そのほとんどのものの間の論理的根拠は何でしたか? それはおそらく有機的で反復的な開発であり、あちこちでいくつかのハッキーな回避策があります(Godotやおそらく他のすべてのゲームエンジンにも見られます)。 つまり、クラッシュが多すぎて、「_ With_」と入力するたびに、Swiftキーボードが「_Unitycrashing_」という単語を予測し始めました。 それは私のワークフローの主要な部分でした。クラッシュ->すべてのアセットを1分間再インポートし、30分間作業し、繰り返します。
私はこれほど多くの冒涜的な単一行動の使用法を見てきましたが、誰のせいにすることができますか? エンジンを使用すると、ポイントライトオブジェクト内に_GameState _ "_ component_"を配置できます。 禁止すべきですか? http通信(または事実上すべての非同期作業)でゲーム状態データが必要な場合、ゲーム状態データがシーンオブジェクトのコンポーネント内にあるべきではないとどのように主張できますか?
それは私のポイントに私を連れて行きます、彼らの異なる開発段階でエンジンを比較することは難しいです、そして確かにGodotは急速に進化していて、機能を追加/削除しています。 つまり、ワークフローを変更し、それに応じて適応させる必要があります。 私はGodotでまともな2Dワークフローを持っています、それは私がUnityで持っていたものより間違いなく優れています。 はい、ベストプラクティスは曇っています。 はい、3人の開発者に質問すると、3つの異なるワークフローがあります。 しかし、それが私にとって新しい問題であるとは言えません。少なくとも、比較した両方のエンジンに存在する問題です。
プロトタイプやテストプロジェクト以外にUnreal(またはその他の関連するゲームエンジン)を実際に使用したことはありません。妥当な深さと比較することはできません。
しかし、どのように?
100万を超える関数が必要になり、100万の空のノードでさえ、Godotには多すぎるため、すべてのスクリプトで子を作成できないことはすでにわかっています。
それはどういう意味ですか、いくつの関数をグループ化する必要がありますか、それとも紙にオブジェクトの継承を計画するために2〜4か月を費やす必要がありますか?
おそらく、すべての関数を1つのスクリプトにまとめますか? Godotはオブジェクト指向で使用できるため、OOPを使用したことがある場合は、スクリプトやシーンの継承を使用したり、クラスを作成したりできます。
私が知りたいのは、Godotが、気象効果、体積霧、大きな地形などの複雑なシステムを備えた大規模なゲームをどのように処理するかということです。
天候の影響? パーティクルノード、太陽、ワールド環境を含むシーンを作成し、ルートにスクリプトをアタッチします。 このスクリプトは天気を制御できます。 空のノードを作成してステートマシンとして使用し、状態ごとに空のノードをアタッチすることもできます(雨、日光など)。 次に、各状態のコードをノードに配置します。 このステートマシンは、ルートスクリプトによって制御できます。 これは非常に読みやすい方法です。
体積霧? 私はこれを新しいFPSデモで見たと思います。
大きな地形? 手続き型の地形メッシュを使用したプロジェクトが1回ありましたが、数年前のラップトップで非常にスムーズに実行されていました。
これらは、OPで話している「大きな問題」ではなく、一部の機能にすぎません。
天候の影響? パーティクルノードを含むシーンを作成します...
さて、私たちはそれよりも少し野心的なことを計画しています:)地域マップを使用して、AIに歩く場所を指示し、最後のチャネルを深さのために維持しながら、雨の排除ゾーンに他のチャネルを使用して、雪が時間の経過とともに蓄積できるようにします。
大きな地形?
広いスペース。 削除する必要のあるノードが多すぎるため、シーンをフリーズせずにVector3(0,0,0)にリセットする方法が必要です。 物理学とすべてが大きなフロートで揺れます。
コンポーネントが非常に肥大化しているため、これまでに使用した他のECSと比較することはできません。
同意しましたが、コンポーネントはひどいものになる可能性があるため、Godotが別の戦略を念頭に置いていても驚かないでしょう。 しかし、Godotがどのような戦略を計画したのか、あるいはそれが実行されたのかどうかはわかりません。
Godotを2か月間学んだことで、小さなゲームの作り方しか考えられませんでした。
Godotの使用を決定するのにあと14日ありますが、エンジンの開発者が大規模なプロジェクトでの作業をどのように想定しているかを説明してくれることを期待しています。
私たちがやりたい最後のことは、ゲームを開発しようとしている間、エンジンの設計に対して上り坂で戦うことです。
@MysteryGMGodotが大きなプロジェクトに使用できないと思う理由がよくわかりません。 すべてを別々のシーンに分割し、OOPを使用して作業を再利用できるため、その設計は大きなプロジェクトに非常に適しています。 大きなプロジェクトでGodotを使用する際の問題が、目標を達成する方法がわからないことである場合は、Godot Discordsヘルプチャネルで質問するだけで、すぐに応答が得られます。
物理学とすべてが大きなフロートで揺れます。
#288を参照
しかし、Godotがどのような戦略を計画したのか、あるいはそれが実行されたのかどうかはわかりません。
最初はそれが一種のエイリアンであることは理解していますが、私にとってノードとスクリプトの使用法は非常に簡単です。 私は間違いなくここでこのコースの(少なくとも)趣味のバージョンを見てみることをお勧めします: https ://gumroad.com/gdquest
それは私のものと非常によく似たノードスクリプト構造を使用しており、エンジンに実際に関係している人々がそれをどのように使用しているかについてのより良い洞察を確実に与えることができます。 著者はgodotドキュメントの主要な寄稿者です。
編集:実際には、コースhttps://github.com/GDquest/make-pro-2d-games-with-godotが必要ない場合は、リポジトリ内のソースを確認できます。
Godotの使用を決定するのにあと14日ありますが、エンジンの開発者が大規模なプロジェクトでの作業をどのように想定しているかを説明してくれることを期待しています。
私はあなたがこれによって正確に何を意味するのかについて少し混乱していると思います。 先ほど例としてハンマーのアナロジーを使用しましたが、ハンマーは一般に使い捨ての基本的な実用的なツールであり、そのアフォーダンスのためにツールが何に使用されるかについて本質的な理解があるため、これは欠陥のあるアナロジーです。
さらに、上記のすべてのシステムのすべての問題をリストアップしましたが、大きなソフトウェアプロジェクトの現実は、アーキテクチャの「選択」ごとに、将来的にいくつかの不利な点が生じることだと思います。途中でもっと協力してください。 それで、あなたは銀の弾丸の提案を探していますか? 率直に言って、ほとんどのUnityまたはUnrealプロジェクトが正確な「推奨」構造に従っているとは思わず、ワークフローが最適になるようにエンジンをフォークすることがよくあります。 私は、すべてのゲームがノードアーキテクチャに関して独自のアイデアを持っている必要があると主張することさえします。 (たとえば、シミュレーションゲームは、サードパーソンシューティングゲームとは非常に異なる構造になります。)
プロジェクト構造の例についてもっと多くのドキュメンテーションを議論することができると思いますが、それはドキュメンテーションへのより多くの貢献の問題だと思います。
シーンを分離し、OOPを使用して作業を再利用します。
前にも言ったように、信号が接続された後にオブジェクトを動かすのは苦痛です。 特に、例外や警告を出さずに動作を停止した場合。
他の開発者が言及した後、サードパーティのリファクタリングツールを使用することにしました。 しかし、それでもゴドット特有の問題を解決することはできません。
物を動かさないと、この問題が発生します(「問題ボード」からの画像)。
そこで、これを修正するために子ノードを作成しました。 約50000を除いて、それらが単なるノードであっても問題を引き起こし始めます。
私たちが知りたいのは、これらの問題にどのように対処するか、Godotはこれらの問題にどのように対処することを計画したかです。 上記のすべてのワークフローをテストしました。
#288を参照
そのおかげで、私たちは休息の世界座標にとても慣れているので、これをチェックしたことはありません。
最初はそれが一種のエイリアンであることは理解していますが、私にとってノードとスクリプトの使用法は非常に簡単です。
問題はそれがエイリアンであるということではなく、問題はそれが別の問題を引き起こすということです。 主に、子を追加すると、子をアンロードしようとすると、最終的にゲームが遅れたり、フリーズしたりします。
それらが単なるノードである場合でも。
ゲームに50,000個のオブジェクトが必要なのはなぜですか? 確かに、これはどのエンジンよりも遅れるでしょう。
ゲームに50,000個のオブジェクトが必要なのはなぜですか?
ノードを使用してオブジェクトにスクリプトを追加するためです。 GodotのUIツールは、コンテナー内のコンテナー内のコンテナーを使用するため、リアルタイムでスケーリングします。
最小のUIは800を超えるオブジェクトです。 これらのコンテナのほとんど。
単一の敵AIは目的のある+/- 8ノードであり、スクリプトをアタッチできるようにそこにのみ存在する+/- 64ノードであるため、50000個のオブジェクトがあります。
各タスクを独自のコードに分割することで、問題がどこにあるかを確認できるからです。 ゲームの特定の部分をすばやく見つける方法は他にないからです。
その場合、カスタムモジュールが適切なオプションであるゾーンに侵入したようです。
http://docs.godotengine.org/en/3.0/development/cpp/custom_modules_in_cpp.html
そこでカスタムノードを作成し、多くのネストを回避できます。
編集:1つの(最小?)UIに対して800個のオブジェクトが悪いデザイン/アーキテクチャを指していると私は主張しますが。
1つのオブジェクトに対して64個に近いスクリプトを作成する方法を真剣に理解できていません。 これは、Godotの問題というよりも、プロジェクトの設計上の問題のように聞こえます(これも、エンジンに遅れをとる可能性があります)。 コードをより少ないスクリプトに統合します。 機能ごとにスクリプトを作成するのではなく、オブジェクトのタイプごとにスクリプトを作成します(「敵」ノードがXYZを実行できる場合は、X、Y、Z機能の子ノードを追加する代わりに、その部分を敵スクリプトに追加します) 。 これを行うためにより高度な機能が必要な場合は、カスタム継承やC#インターフェイスを利用できます。
その場合、カスタムモジュールが適切なオプションであるゾーンに侵入したようです。
これが私たちが疑問に思っていることの1つであることがわかります。なぜなら、カスタムModulseが必要な場合は、代わりにGodotエンジンを編集するだけでC ++を知っているからです。
Godot preload()が疑わしい場合は、#includeを安全に使用できることがわかっています。 それがどれほど安定しているか、または欠点があるかどうかは誰にもわかりません。
1つのオブジェクトに対して64個に近いスクリプトを作成する方法を真剣に理解できていません。
シンプルで、すべてのAIは、マイナーなタスクではなく、多かれ少なかれ64のタスクを実行できます。
たとえば、スクリプトはSquadFlightPattersであり、ここには20個すべての飛行フォーメーションがあります。次にSquadFlightPattersCosmeticがあり、飛行パターンに関連するアニメーション、サウンド、およびパーティクルのみを解決します。
現時点での私たちのルールは、メカニックからのユーザーフィードバックを分割することです。
「Enemy」ノードがXYZを実行できる場合は、X、Y、およびZ機能の子ノードを追加する代わりに、その部分をEnemyスクリプトに追加します。
画像と疑似アンリアル、別名コントローラーと中間を見ると。
カスタムモジュールが必要な場合はC ++を知っているので、代わりにGodotエンジンを編集します。
モジュールの作成は、エンジン自体を変更するよりもはるかに簡単であることがわかりました。エンジンは、エンジンに組み込まれるのではなく、その上に構築されるためです。
ただし、このような大きな数値へのスケーリング、特にウィジェットごとに数百または数千のノードを持つUIを想像することはできません。
OPで参照されている問題への対応:
- アセットのシステム全体のインストールで適切な依存関係管理を追加します。 アドオンをプロジェクト自体から移動して、変更のために元に戻す方法を使用します
- カスタムノードの拡張を容易にし、言語間のスクリプト継承を可能にします
- アセットの場合に超長いパスを回避するために、スクリプトをクラス名と名前空間で参照できるようにします。
スクリプトクラスは最後の問題を解決します。 名前空間は、他のスクリプトのエイリアスとして機能する定数を使用してトップレベルのスクリプトクラスを作成することで作成できます。 3.1でエディターのシーンドックに加えた変更により、カスタムスクリプトの拡張も非常に簡単になりました。 言語間の継承に関しては、正式に実装されることはありませんが、MultiScriptが再導入された場合、それらはそれをかなりうまく偽造する可能性があります。
現在、MultiScriptは基本的に基本エンジンタイプを拡張するすべてのスクリプトをサポートしているため(したがって、すべてが異なることを行うが、互いに関連していない、異なる言語からの複数のノード拡張スクリプトを持つことができます)、実際にはほとんど次のように機能しますクロスランゲージ特性システム...ある種。 MultiScriptを再追加するのはかなりクールだと思いますが
OPで提起された問題の多くは、問題に対処するための複数の潜在的な方法があり、それぞれがさまざまな非効率性を持っている可能性があることを中心に展開しています。 通常、最適な処理を行う特定の方法がある場合、エンジンはメインのC ++エンジンに独自の実装を提供し(スクリプトやプラグインは不要)、それが推奨される使用法です。
そのようなクラスが存在し、人々がそれを使用していない場合、それは1)ドキュメントを適切にチェックして、エンジンによってニーズがすでに満たされているかどうか/エンジンがどのように使用を提案しているかを確認していないことを示しています。エンジン/組織は、ドキュメントをユーザーが見やすくしたり、アクセスしやすくしたりするのに十分な仕事をしていません(ユーザーが存在するリソースを見つけられないため)。
問題1を修正するために行うべき唯一のことは、それらの人々が問題を発声し、他の誰かが彼らをドキュメントまたはQ&Aサイトにリダイレクトして解決策を見つけるのを助けることです。 エディターから直接Q&Aサイトを閲覧して使用できるようにすることを提案する問題(#23043)を作成しました。これは、問題2で大いに役立つはずです。理由はリンクに記載されています。
(編集:問題を解決する方法がたくさんあり、それらの方法の1つが他の方法よりもはるかに優れていて、 Godotがまだ独自のネイティブソリューションを実装していない場合、それは新しい機能として提案するものになりますこれは、人々がGDScript /シェーダーコードなどで独自のSimplexNoiseアルゴリズムを作成していたため、SimplexNoiseのものを追加した方法です。
あなたが描いた「問題ボード」に基づいて、あなたが抱えていた問題は、多重継承がサポートされていない(または良い考えではない)ということです。そのため、親に機能を付与するコンポーネントノードを使用しました(これは私には合理的に聞こえます)。 単にノードが多すぎるためにゲームの遅延の問題が発生している場合は、一般的なアプローチ(認識して助けを求めているように見える)に問題がある可能性が高いように思われますここで識別するため)。
OPでのワークフローの例については...
Unityアプローチ、子ノード:
ペアリングロジックを作成することを前提として、子ノードを使用することは理にかなっています。 これは、トレイトシステムが役立つ理想的な場所です(ペアリングロジックを一度記述して、必要に応じてどこにでも複製できるようにするため)。 私はよく、コンポーネントが親/親なしで、関連する信号を自動接続/切断するときに、親の「ターゲット」として自動的に設定される方法でコンポーネントを作成します。 これには、 _notification(what)
のNOTIFICATION_(UN)PARENTED通知を使用できます。
コントローラを使用したUE4アプローチ:
Godot 3.1では、スクリプトにスクリプトクラスを割り当てることができるため、スクリプトをプリロードする必要はありません。 この場合、Godotではノードにタイプ名を割り当てることができますが、これはスクリプトに固有であるため、注意が必要です。 シーンは同じ扱いを受けません。エンジンコアにたくさんのものを追加する必要があるため、おそらくそうはなりません(コア開発者はかなり敏感になる可能性があります)。
また、どのようにして多くの重複コードを取得しているのかわかりませんか? 複数のクラスが同じロジックを必要とする場合は、そのロジックを1つのノードにバンドルし、Unreal(コンポーネント、子アクター)、Unity(MonoBehavioursまたは子GameObjects)の場合と同じように、そのロジックを必要なクラスで再現します。 、またはコードの再利用を減らすために依存関係を所有オブジェクトにシフトする他のほとんどすべてのエンジン。
プリロードを使用したPanda3Dアプローチ:
NodeRefsはまだ問題ではないため、このアプローチには多くの問題があることを理解できました。また、3.2で修正したいと思っている現時点では、リソーススクリプトのエクスポートに問題があります(ただし、おそらく自分で修正することもできます)。簡単に言えば、かなり小さいです)。
WTFスクリプトアプローチ:
私はあなたがここで抱えているすべての問題を本当に理解していません。おそらく私たちには多くの文脈がないからでしょう。
インスタンスシステムとの競合。 なぜなら、信号が最も上向きに接続している間、インスタンスは下向きに流れるからです。
子孫で親のシグナルトリガー動作をいつ実行したいですか? 親に子孫とそのメソッドを直接取得して呼び出させないのはなぜですか? 親が子供を見る危険はありません。 これは、C ++オブジェクトがその構造体またはクラスメンバー変数(?)にアクセスできないようにする必要があると言っているようなものです。
小さな無意味なスクリプトがただうろついています。 彼らがするのは、信号を送信し、単一の値を追跡することだけです。
これは、プロジェクトの設計が良くないことの兆候です。 それは、ゲーム内のすべての特異な相互作用をそれ自体の個人的なオブジェクトによって追跡させるという問題です。 これは、どの観点から見ても、実際には理想的ではありません。
非常に多くの信号が接続されているオブジェクトを移動することは、少なくともイライラします。
どのように? 私は一般的に、シーンファイルの接続をハードコーディングしているか、ノードを移動することを目的としている場合は、ノードの信号をアルゴリズムで接続および切断していることに気付きました。 それは私の目的を十分に果たしましたが、特定の問題がある場合は、それらを共有することで他の人があなたを助けることができます。
シグナルとグループを使用すると、警告なしでゲームのすべての部分を失敗させることができます。
したがって、存在設計を介したブール値の問題です。 別の方法は、ALLオブジェクトをループし、それらが基準に一致するかどうかを確認し、一致する場合はロジックを実行し、一致するが正しくない場合はエラーをスローすることです。 シグナルとグループの場合、動作はセット内のすべてで自動的にトリガーされるため、セットから外れた場合、実行中に問題が発生したことを検出する方法はありません。 この種の問題を見つける唯一の方法は、グループ/信号が最初に配置されているセットアッププロセス中です。
とにかく、それは私のもののすべての経験でした。 私たちがあなたのプロジェクトとそれが実際に何をしているのかをもっと知ることは私たちにとってもっと多くのことを助け、あなたの特定のユースケースのための提案をすることができます。
いずれにせよ、ここで提起した問題は、GodotEngineの設計または実装自体に関する「新しい」問題ではないようです。 Godotは人々にAPIを提供し、人々がそのAPIをどのように使用するかは彼ら次第です。 特定の機能をGodotでより統合/利用可能にする方法(たとえば、MultiScriptの再活性化)についてのアイデアがある場合は、それは素晴らしい提案です。
とはいえ、ここでの質問は、「Xのようなシステムを設計するための最良の方法は何か」ということのように思われますが、これは実際にはGitHubの問題ではありません。 「ベストプラクティス」のような質問については、Q&Aサイトでより適切なようです。 それとも、この種のユースケース固有の情報をより明確に/公開するための手段を提供する必要があるという提案です。これがまさに私のQ&Aの問題です。
スクリプトクラスは最後の問題を解決します。
長い返信をありがとうございました。それはたくさんあり、明らかに書くのに少し時間がかかりました。
スクリプトクラスについて聞いてうれしく思います。3.1は使用しませんでした。 FPSデモを実行するためだけに。
しかし、MultiScriptが再導入された場合、それらはそれをかなりうまく偽造する可能性があります。
GodotがMultiScriptを実装しないのであれば、それは完全に理解できます。 実のところ、GitHubの多くのユーザーが、私たちが試したのと同様のワークフローソリューションを探していることを指摘していました。
子孫で親のシグナルトリガー動作をいつ実行したいですか? 親に子孫とそのメソッドを直接取得して呼び出させないのはなぜですか?
これを説明したほうがいい気がします。 当時、私たちは非常に大きなスクリプトを持っていて、それぞれがおよそ+/- 30の関数を持っていました。 そのため、すでに大きなスクリプトに余分なシグナル関数を追加することは避けたかったのです。
その結果、大きなスクリプトから作業をオフロードするための緩いスクリプトを作成しました。
これは、プロジェクトの設計が良くないことの兆候です。
それが問題の根本です。 主に、Godotコミュニティが推奨する多くのデザインと、チュートリアルからのいくつかのデザインを試しました。
1.)最初は非常識な継承がありましたが、ブランチシーンを保存したり、オブジェクトを他のシーンに移動したりすると信号が切断されることが明らかになると、すぐに放棄されました。
2.)これに続いて大きなスクリプトを作成しました。 それぞれが何をするのかを説明するためのこれらのスクリプトの抽象的な名前を除いて、問題を見つけるのは困難でした。
関数の名前がどこで問題を引き起こしているのかはわかっていましたが、正確にはどこにあるのかはわかりませんでした。
3.)次に、マニュアルを読むことで、子ノードのアプローチを見つけました。 直接ノードが可能で、エディターで構造を確認できるため、魅力的すぎた可能性があります。 また、フィルタリングして、必要なスクリプトを正確に見つけます。
結局ここで私と一緒になり、最後の返信は私が疑問に思っていた多くのことを扱っていたと思います。 ここは午前2時なので、明日は再確認する必要があります。
「Xのようなシステムを設計するための最良の方法は何ですか」...これは実際にはGitHubの問題ではありません。
他のオプションのほとんどを使い果たしたことを指摘したいと思います。 私たち一人一人がQ&Aフォーラムで質問し、コミュニティで友達を作り、そこから例を集めました。 説明を探してドキュメントをスキャンしました。
私が説明したワークフローはすべて、これらのワークフローを使用するGodotユーザーから説明されたものです。 それぞれが前述のエンジンで動作しますが、Godotではうまく動作しませんでした。
私たちのメインプログラマーがテーブルに頭をぶつけて誰かの首を絞めていることを除いて、最後のワークフローの種類だけが機能しました。
問題の解決策を見つけるのに問題が発生していることをお読みいただき、申し訳ありません。 すでに長い回答がありますので、あまり会話を乱雑にしないようにしますが、現時点では、ニーズから生じた特定の課題を解決するために、より多くのコンサルタントが必要になるようです。
主に、Godotコミュニティが推奨する多くのデザインと、チュートリアルからのいくつかのデザインを試しました。
コミュニティの私たちのほとんどは、比較的小規模なプロジェクトで働いています。 チュートリアルで特定のシステムの要点と構造を理解するために、多くのノードを使用しています。 これはほとんどの人にとってうまくスケーリングします。 ただし、小規模または中規模のゲームで機能するものは、大規模なゲームには適用されません。
@willnationsdevが以前に言ったことに続いて、パフォーマンスの観点からも、エディター自体で管理するコードを少なくするためにも、ゲームのスケーリングを支援するバックエンドコードを検討する価値があるかもしれません。 ここにいる多くの人のように、私はより大きなプロジェクトの経験がないので、それ以外に多くのことを助けることはできません。 幸運を!
こんにちは、もう1つ質問があります。
建物と水のような2つの無関係なオブジェクトがあり、これらのオブジェクトのスクリプトを相互作用させたい場合、ノードやプリロードなしでこれを行うにはどうすればよいですか?
水は風合いなので、建物にもぶつかりません。
@MysteryGM建物と水を表すノードが必要ないということですか、それとも単にスクリプトをそれらにアタッチする必要がないということですか? ノードを含む単一のデータを除いて、シーンツリー内に何らかの形で存在しない処理用のデータがあることには何の問題もありません。
タイプのすべてのインスタンスにスクリプトをアタッチして個別に処理する代わりに、ECSアプローチを採用する場合は、タイプに応じてノードを反復処理して処理する単一の「システム」ノードを使用できます。それらを割り当てたグループ。 個々の詳細情報のためにノードにスクリプトを添付することを避けたい場合は、時間の長さに応じてその情報をシステムに保存することもできます。 これにより、ノードの重量が軽くなり、同じタイプの何千ものエンティティを操作するときに効率が向上します。
50.000を持っていると、GodotのSceneTree -and-nodesオブジェクトベースのメタファーが役立つポイントをはるかに超えています。
これは他のエンジンと大差ありません。Unityではゲームオブジェクト、GC、またはUE4で同様の制限に達する可能性がありますが、ブループリントのスケーリングには問題がありますが、何よりも、その量の何かがあるとデフォルトになりますビジュアルエディタはもはや役に立たず、提供されているツールは壊れ始めるか、少なくともパフォーマンスが低下します。
すべてのエンジンで、ソリューションはほぼ同じです。独自のソリューションを構築します。 それらが何であるかは、エンジンよりもゲーム、アーキテクチャ、および詳細に依存します。
マネージャークラス、pub-sub通信バス、メッセージブローカー、パーティクル、オブジェクトプール、GPUに作業をオフロードするカスタムシェーダー、計算シェーダー、スレッドまたは他のプロセス/サーバーへの処理の移動と同様のインスタンス化マネージャーがあります考えられる解決策のための大量のビルディングブロック、およびどのビルディングブロックを組み合わせる必要があるかは、特定の問題セットによって異なります。
Unityは、新しいECSインフラストラクチャを使用して、これらの一部を簡単にします。 UE4についてはよくわかりません。 最後に、この高度なレベルでは、重労働のほとんどを自分で行う必要があります(または、経験豊富な人を雇って代行してください)。
UE4とUnityは、古く、確立されている限り、より簡単です。したがって、このようなスケーリングの問題に遭遇した人の数が多くなり、それを解決するために利用できる知識(および雇用可能な人材)が増えます。
しかし、実際には、結局のところ、エンジンはあなたをそこまで運ぶことはありません。 すべての野心的なゲームは、どのエンジンでも制限にぶつかります。 同様の問題を解決するために必要な、UEまたはUnityの中規模から大規模のゲームの例を数多く知っています。 それらを解決するか、スコープを縮小してください。
Godotゲーム開発者がエンジン開発者に必要としているのは、複雑なオブジェクトやシステムを作成するための公式ワークフローを明らかに減速することです。
それは主にあなたのゲームに依存します。 どんな大型エンジンでも、これに対する正解はありません。
Unityでgameobjects-scene-basedアプローチを使用する必要がありますか? またはハイブリッドECS? まったく新しいECS? どのレンダリングパイプラインを使用しますか?
UE4プロジェクトでブループリントまたはC ++を使用しますか?
すべてのソリューションに1つのサイズで対応できるわけではないため、すべてのエンジンには、豊富な選択肢、大量のワークフロー、および多くの自由があります。
したがって、Godotで特定のゲームにアプローチする方法、ゲームを構造化する方法、使用するアーキテクチャについて具体的なアドバイスが必要な場合は、より多くのコンテキストと情報を提供する必要があります。
あなたが達成したいことを教えてください、そして多分誰かがアドバイスでチャイムを鳴らすことができます。 そうでない場合、唯一の方法は、経験豊富なGodot開発者をコンサルタントとして雇うことかもしれません。
私はGroudにのみ同意できます:
すべてのソリューションにはトレードオフがあるため、「公式」ワークフローを作成する意味はありません。
@mhilbrunnerここで悪魔の代弁者を演じるだけですが、より良いエンジン設計(パフォーマンスが重要な場合の大部分のバットでの適切なECSのような)は、これらの制限の多くを、ほとんどすべてのゲームが実際に経験するよりも大幅に高くします(これが新しいRust Amethystの方法です)ゲームエンジンは、たとえば焦点を合わせるために構築されています)。
しかし、うん、私はGodot(2)でECSのようなことをしました。それは、効率と機能の分散の点で、シーンツリーインスタンス化スタイルよりもはるかにうまく機能しました。 Godotには有用なプリミティブがいくつかないため、これは実行できますが、少し苦痛です。
@ OvermindDL1
私は自分自身でしか話すことができず、他のGodot開発者ではなく、UE、Unity、Godotの経験しか持っていないので、RustAmethystについては知りません。
Godotには有用なプリミティブがいくつかないため、これは実行できますが、少し苦痛です。
そのようなプリミティブを追加することが理にかなっている場所/ Godotがそのようなユースケースにどのようにうまく対応できるかについて話し合うことは非常に価値があると思います。 多分この問題ではありません:)
しかし、このフィードバックを何らかの方法で収集する必要があります。
また、エンジンによって制限が異なることに同意しますが、UnityとUE4でも同様の障壁にぶつかる人がいます。 多分後で、多分それらはより高かった-しかし最後に、あなたはあなたがどんなエンジンでも遭遇する問題を解決することができる必要があるでしょう。 :)
@MysteryGM建物と水を表すノードが必要ないということですか、それとも単にスクリプトをそれらにアタッチする必要がないということですか?
ウォーターシェーダーにフィードするウォーターオブジェクトにスクリプトを添付しました。 そのため、ウォーターノードにスクリプトをアタッチできなくなりました。
建物にリソースの生成を制御し、ドアなどを接続するスクリプトを添付しています。 そのため、コードを追加したくないスクリプトもあります。
両方のオブジェクトにすでにコードが含まれているので、今何をしますか? これ以上ノードを追加することはできませんが、プリロードが可能な解決策であるかどうかはまだ不明です。
私がそれをOOP設計と表現した場合の私の質問は、2つのスクリプトが互いにどのようにインターフェースにアクセスするかということです。
問題は、GDscriptが他のスクリプトに直接アクセスする方法がないように見えることです。
火で木を燃やしたい場合は、木->延長->火または火->延長->木が必要です。
@MysteryGM :1つのヒント:シグナル。 ターゲットがあなたのウッドである場合、火はシグナルバーン(ターゲット)を持つことができます。
2つのスクリプトはどのようにして相互のインターフェイスにアクセスしますか?
$NodeWithScript.do_function()
?
_ / meはまだ悪魔の代弁者を演じています、これをGodotで「すべき」ことの尺度としてとらえないでください。せいぜいそれはbikesheddingです_
私は自分自身でしか話すことができず、他のGodot開発者ではなく、UE、Unity、Godotの経験しか持っていないので、RustAmethystについては知りません。
UEはActorSceneTreeモデルを使用します。 UnityはECモデルを使用しました(最近、ECSを構築し、古いECモデルを廃止しましたが、まだ完全ではありませんが、有望に見えます)。 そして、GodotはComponentSceneTreeモデルを使用します。 ECSは、データフローパターンのサブセットです(具体的には、ECSを一般化したものです)。
ECSの簡単な要約:
「エンティティ」は単なる整数IDですが、ほとんどのエンジンは、生成とエンティティのインデックスを単一のint32(8ビット生成と24ビットインデックス)またはint64(それぞれ32ビット、int64はECSで実際に許可されているため、はるかに一般的です)にパックします。そのようなかなりの量のエンティティにスケーリングするため)。
「コンポーネント」は、C / C ++用語のPOD構造体であり、機能を含むことは絶対にありません。 一般的に、それは簡単にmemcpy'ableである必要があります。
コンポーネント「テーブル」はコンポーネントのストレージであり、最も基本的にはサイズ変更可能な配列にすることができますが、一般的にいくつかのタイプが使用される傾向があります。
「システム」は、最も基本的なコンポーネントの結合セットを受け取る関数ですが、ほとんどのライブラリには非仮想クラスまたはモジュールなどがありますが、結合されたコンポーネントのセットを操作して「何かを行う」ことができます。これには、コンポーネントの値の変更、コンポーネントの追加または削除などが含まれる可能性があります。いくつかの例:
内部的には、ECSは、データのマッピングを設定するためにサブスクライブできるデータベースと考えることができますが、適切に作成されていれば、非常に最適化されています。 どのシステムを他のどのシステムの前に実行する必要があるか、およびどのシステムが重複しないように動作するか(読み取りまたは読み取り/書き込みに依存)を知っていれば、呼び出しを簡単にマルチスレッド化することもできます。 (私はAmethystを使い続けており、例としてspecs
と呼ばれるECS固有のライブラリ部分です。これは、古いC ++ ECSライブラリの移植から作成に携わったためです)スペックブックには、「なぜ」ECSについて多くの詳細が記載されています。方法、効率、使用法など...アメジストは、特にECSを一般的なゲームシステム、レンダリングなどでどのように使用するかについて、さらに詳しく説明します。
よく書かれたC ++ ECSライブラリを見たい場合は、 https://github.com/skypjack/enttを見てください。私が作成しなかったすべてのC ++ ECSライブラリから、作成したものが最適のようです。全体的に(スペックは私の単純なテストではまだそれを上回っていますが、それほどではありません。これは、スペックがこれまでに比較したすべてのものよりも大幅に優れていることを考えると印象的です)。
ECSの一般的な「使用法」は、「エンティティ」(整数のみ、データなし)があり、コンポーネントをエンティティにマップする一連のテーブルと、実際に作業を実行するシステムがあることです。 GDScriptの擬似コードでは、単純なAPIだと思いますが、シーンツリーはそれを念頭に置いて設計されていないため、Godotシーンツリーに「統合」するという奇妙な慣習があります。
# All of this would generally be wrapped up in one or more function calls for easy
# building.
# Create a new entity
var e = createEntity()
# Map it to some Components, starting with a godot scenetree component
# I'm using long names to be descriptive, but eh...
var eNode = scenetreeComponentTable.set(e, SomeNodeType())
# Generally things like the transformation matrix and so forth would be their own
# components, but since the godot scenetree already bakes all that in then just
# deal with it all via the node type, you definitely lose a little efficiency doing
# it this way though since nodes involve multiple virtual calls to access and
# the usual ECS patterns entirely get rid of virtual calls with potentially only
# the occasional indirect calls inside a table (maps, etc...)
# 8x4 inventory slots
inventoryComponentTable.set(e, 8, 4)
# 1 fuel slot, accepts items that have the "burn" tag
fuelStorageComponentTable.set(e, 1, "burn")
# Give this entity the furnace component that uses the "basicFurnaceRecipes" recipes
furnaceComponentTable(e, "basicFurnaceRecipes")
# Add other components
# All of the above component mappings could also be in, say, a JSON file, and
# loaded something as such:
componentTables.map(e, "res://entity_types/basicFurnace.json")
# Or maybe via a preloaded JSON object or so
# Once at startup:
# And you could make a system something like, I'll use a GDScript class for this:
val furnaceCookSystemHandler = systems.register(FurnaceCookSystem.new())
furnaceCookSystemHandler.staticTickRate(0.05) # 20 times a second exactly
# Where the `FurnaceCookSystem` could be something like:
class FurnaceCookSystem:
def _entity_matchers():
furnaceBurnMatcher =
componentTables.matcher().
write(inventoryComponentTable).
write(fuelStorageComponentTable).
writeEither(inventoryChangedComponentTable, furnaceCookingComponentTable)
read(furnaceComponentTable)
return [furnaceBurnMatcher]
# Assume we have matching semantics here to destructure a list, I'm lazy...
def _entities_process([furnaceBurnEntities], delta):
# This function takes a list of entity sets in the same order as the matchers
# returned above.
while entity in furnaceBurnEntities:
val furnace = furnaceComponentTable[entity] # or .get(entity) or whatever API
val cooking = furnaceCookingComponentTable[entity]
if cooking == null or cooking.cookTimeRemaining <= 0:
if cooking != null:
if inventoryComponentTable.put(item) == False: # No space, try later
continue
# Get next item that has a "burnable" tag, if any
val item = inventoryComponentTable[entity].getAndRemoveFirstOf("burnable")
if item == null:
furnaceCookingComponentTable.remove(entity)
else:
cooking = furnaceCookingComponentTable.set(entity, item, furnace.cookTime * getCookTimeModifierOfItem(item))
else:
cooking.cookTimeRemaining -= delta
# ... whatever other functions are useful to the system
# Then of course just with the right components on any entity it will just work
# 'as' a furnace. You can have a whole variety of 'generic' systems that can be
# mixed and match with impunity. If you want a random rock that can be a furnace
# then just add the proper components, or if you want an Ent that can both be
# chopped down like a tree for wood but will also attack the player then just add
# the proper components, etc.... etc....
@MysteryGM :1つのヒント:シグナル。 ターゲットがあなたのウッドである場合、火はシグナルバーン(ターゲット)を持つことができます。
申し訳ありませんが、インスタンスではなくスクリプトを意味しました。 Godotツリーのノードを必要とせずにスクリプトを相互作用させたい。
申し訳ありませんが、インスタンスではなくスクリプトを意味しました。 Godotツリーのノードを必要とせずにスクリプトを相互作用させたい。
私はあなたの問題を誤解しているかもしれませんが、GDScriptでクラスを作成することですでにこれを行うことができると確信しています。 エントリポイントとして機能するには、ノードに自動ロードまたは少なくとも1つのスクリプトが必要です。
また、C#を試しましたか? スクリプトをノードにアタッチする以外の方法でノードと対話し、ノードを制御するスクリプトを含む複雑なシステムを作成しようとしている場合は、そのようなシステムのGDScriptよりもC#の方がはるかに良い時間を過ごすことができます。
@MysteryGMシーン内のノードを使用せずにスクリプトを相互に対話させるには、少なくとも、ロードされたバージョンのスクリプトリソースを取得する必要があります。 3.0でこれを行う唯一の方法は、ファイルパスごとにスクリプトをpreload
/ load
することです。 3.1は、スクリプトに付けられた名前がグローバルに登録されるGDScriptおよびNativeScriptの「スクリプトクラス」機能を追加します。 GDScriptは、エンジン内のこれらのグローバル登録を言語のグローバル変数に手動で変換します。
次に、 Script
リソースがある場合は、スクリプトで静的メソッドを呼び出すか、 .new()
を呼び出して$#$ ScriptInstance
$#$を取得してから、メンバー関数を呼び出したり、メンバー変数にアクセスしたりできます。 Script
がオブジェクト、参照、リソース、またはその他の非ノードタイプを派生している場合は、 Script
/ ScriptInstance
のインスタンスを作成するだけで取得できます。静的/非静的コンテンツ。 ノードの場合、SceneTreeアクセスを必要とするもの( get_node
など)を除いて同じことが当てはまります。その場合、最初にadd_child
を使用してSceneTreeに追加する必要があります。
上記のすべては、Godotで使用されるすべてのスクリプト言語に適用されます(ただし、プリロードは、私が信じる特定の言語に固有の操作です...)。
ファイルパスによるスクリプト。 3.1は、GDScriptの「スクリプトクラス」機能を追加します
3.1はいつ正式にリリースされますか?
@MysteryGMマイルストーンの完了率が十分に高い場合/コア開発者が、ビルドが「安定している」と見なすのに十分な進捗があると判断した場合。
マイルストーン: https ://github.com/godotengine/godot/milestone/7
比較のために、2.1と3.0は現在99%完了しています。 それが彼らがライブになったときのステータスであるかどうかはよくわかりません。
基本的に、答えは「準備ができたら」です。
ご回答ありがとうございました。お時間を割いていただき、誠にありがとうございます。
Godotは当時の私たちのニーズに合わないようです。 将来的には、エンジンを再び使用する機会が得られるかもしれません。
火で木を燃やしたい場合は、木->延長->火または火->延長->木が必要です。
@MysteryGM
ここを参照してください。
解決策(エンジンや言語に関係なく)は、火と森の間の相互作用を制御する「システム」スクリプトを持つことかもしれません。 このプレゼンテーションはコンポーネントに焦点を当てていますが、システムをオブジェクトで動作させることもできます。
C#では、 Wood
はFire
が使用するIBurnable
を実装していると言えます。
こんにちは、継続的な懸念に感謝し、 @ willnationsdevのサポートに本当に感謝しています。 エクスポートリソースソリューションとしてのスクリプトには、多くの可能性があると考えています。 #22660で述べたように。
使用するエンジンを決定するのにまだ10日あるので、Godotでもう少し試してみました。
私たちはワークフローの問題を調査してきましたが、プログラマーがそれを最もよく言っていると思います。
「Godotの開発者は、Githubのすべての問題を独自の投稿に保持し、常に1つのバグに対して1つの問題を開きますが、エンジンに同じワークフローを許可しません。」
スクリプトを作成する必要があり、それを階層に追加する必要があるという事実。
火と森の間の相互作用を制御する「システム」スクリプト。 そのプレゼンテーションはコンポーネントに焦点を当てています
はい、それが私たちが望んでいることですが、GDscriptでどのようにそれを行うのですか?
C#では、WoodはFireが使用するIBurnableを実装していると言えます。
Godotには、インターフェイスと同じことを行うためのダックタイピングがあります。 Burningを別のクラスにして、階層にノードを追加しなくても再利用できるようにする必要があります。
私たちが欲しいのは、火、燃える、木です。 火(木+燃焼)は必要ありません。
このワークフローの利点は、書き込み可能なすべてのオブジェクトを修正する必要なしに、それ自体で書き込みをデバッグできることです。
C#では、Burningを独自のクラスとして宣言します。 パブリッククラスBurningと私たちの問題は解決されました。
C ++では、バーニングと問題解決を含めます。
はい、それが私たちが望んでいることですが、GDscriptでどのようにそれを行うのですか?
@MysteryGM
パフォーマンスの最適化に飛び込むことなく、私が提案しているのは、インタラクション解決を別のシステムスクリプトに移動することです(火の中ではなく、木ではありません)。 最も単純な場合のシステムは、世界中のすべてのオブジェクトの配列を保持し、それらの相互作用を処理できます。 この場合、オブジェクトは型を気にする必要はなく、システムだけが気にします。
処理を高速化するために、実際に衝突したオブジェクトのチェックのみを実行する場合があります(たとえば、衝突が発生したときにオブジェクトからシステムにsignal
を送信するなど)。
スクリプト相互参照のGDScript固有の例(バージョン3.0の場合):
ここでEnemy
はタイプ/インターフェースとして機能し、 is
演算子を使用して確認できます。
# Cache the enemy class.
const Enemy = preload("enemy.gd")
# Use 'is' to check inheritance.
if (entity is Enemy):
entity.apply_damage()
ここでrunnerGame
は、パス/ root / runnerを持つ_autoload_シーン(別名シングルトン)を指します。
onready var runnerGame = get_node("/root/runner")
onready var runnerScript = preload("res://runner/runner.gd")
func _ready():
runnerGame.setMode(runnerScript.SPAWN_TITLE)
ここでは、ボタンの「押された」 signal
をハンドラーに接続します(別のオブジェクトとスクリプトにある可能性があり、同じものを参照するためにself
を使用しています)。
func _button_pressed(which):
print("Button was pressed: ", which.get_name())
func _ready():
for b in get_node("buttons").get_children():
b.connect("pressed", self, "_button_pressed",[b])
こちらのドキュメントもご覧ください。利用可能な機能が他にもいくつかあります:http: //docs.godotengine.org/en/3.0/getting_started/scripting/gdscript/gdscript_basics.html#inheritance
こちらのドキュメントも参照してください。利用可能な機能が他にもいくつかあります。
トピックへのご意見ありがとうございます。 継承の問題は、クラスを実装するときにクラスのすべての関係を知っている場合にのみ機能することです。
次に例を示します。
ステップA。
MeshInstance + HomingScript = HomingMissile 。
しかし、ホーミング地雷が必要な場合は問題があります。
(MeshInstance + ProximityScript)= Landmine 。
(MeshInstance + ProximityScript)+ HomingScript = ERROR複数のスクリプト
(MeshInstance + ProximityScript)+(childNode + HomingScript)=非表示のノードのみが移動するため、失敗しました。
(MeshInstance + ProximityScript)+(childNode + ExtendedHomingScript)=成功します。これで、Homingクラスを拡張して、子ノードからノードを所有できるようになりました。 HomingLandmineを取得します。
今を除いて、ホーミングミサイルとランドマインの両方がホーミングクラスから拡張されるべきであると主張することができます。
StepB。
HomingMissile [ホーミングから]
HomingLandmine [ホーミングから] [+ ProximityScript]スクリプトがコピーされ、地雷に貼り付けられました。
本番環境の後半では、他のスクリプトでも同じことが起こります。
StepC。
地雷[近接から]
ProximityAlarm [プロキシミティから] [+ AlarmScript]
// HomingLandmine [from Proximity] [+ HommingScript] //これで地雷もここに収まります。
したがって、StepBの適切な継承を見つけるために、StepAを実行し続ける必要があります。 StepFなどを超えてこのパターンを繰り返し続けます。
StepAを延長する方法を見つけました。最上位ノードにスクリプトを追加することを避け、常にそれをSpatialノードまたはプライマリノードにします。
(Spatial + MeshInstance + ProximityScript)+ HomingScript = HomingLandmine
これがまったく同じ問題であることを除いて、より高価なParentSpatialがあります。 childNodeの代わりに。
ご迷惑をおかけしましたことをお詫び申し上げます。
@MysteryGM
「Godotの開発者は、Githubのすべての問題を独自の投稿に保持し、常に1つのバグに対して1つの問題を開きますが、エンジンに同じワークフローを許可しません。」
スクリプトを作成する必要があり、それを階層に追加する必要があるという事実。
..。
私たちが欲しいのは、火、燃える、木です。 火(木+燃焼)は必要ありません。
このワークフローの利点は、書き込み可能なすべてのオブジェクトを修正する必要なしに、それ自体で書き込みをデバッグできることです。
..。
C#では、Burningを独自のクラスとして宣言します。 パブリッククラスBurningと私たちの問題は解決されました。
C ++では、バーニングと問題解決を含めます。
この場合、Godotの機能に違いはないことを理解する必要があります。 頼りになる解決策は、独自のスクリプト(この場合は「Burning」)を使用してサブノードを作成することですが、Burningを独自のクラスとして定義し、静的関数を介してインクルード/使用することができます(またはインスタンス化してからプロパティ/メソッドを使用)
Unity / ScriptableObjectアプローチの場合、同じ目的でGodotのリソーススクリプトを使用できます。
火と森の間の相互作用を制御する「システム」スクリプト。 そのプレゼンテーションはコンポーネントに焦点を当てています
はい、それが私たちが望んでいることですが、GDscriptでどのようにそれを行うのですか?
これを行う最も簡単な方法は、ある種の自動ロードノード/シーンを使用することです。 その理由は、(使用しているノードの数を最小限に抑えるために)さまざまなシステムすべてに大量のリソースを持つ1つのノードのみを使用している場合でも、ツリー内にあるノードにアクセスしたい場合があるためです。デルタ時間、入力データ、イールド操作(特に信号使用量と組み合わせて)、アニメーション/トゥイーン/タイマーノードにアクセスできることを確認すると、リストは続きます。 さらに、オートロードとして、GDScriptはノードのグローバル変数を再度生成し、コードベース内のどこからでも「システム」に名前でアクセスできるようにします(この場合はスクリプトクラスを使用するための別の適切な代替手段)。
私は実際に古いWIPプラグインであるgodot-skillsの大規模なリファクタリングを行っています。これは、これだけでなく、さらに多くのことを網羅していると信じています。 このトピックに関する(申し訳ありませんが、長い) redditスレッドをお読みください。 これには、サーバーアーキテクチャ(Godotの基盤となるアーキテクチャと同様)で協調型マルチスレッドを使用して、同様に汎用的で再利用可能な対話型システムを実装することの実行可能性を調べることが含まれます。
ところで、このトピックについてリアルタイムでチャットしたい場合は、同じユーザー名を使用しているReddit / Discord / Twitterで私にpmしてください。
@MysteryGM
MeshInstance + HomingScript = _HomingMissile_。
しかし、ホーミング地雷が必要な場合は問題があります。
(MeshInstance + ProximityScript)= _ Landmine_。
(MeshInstance + ProximityScript)+ HomingScript = ERROR複数のスクリプト
(MeshInstance + ProximityScript)+(childNode + HomingScript)=非表示のノードのみが移動するため、失敗しました。
(MeshInstance + ProximityScript)+(childNode + ExtendedHomingScript)=成功します。これで、Homingクラスを拡張して、子ノードからノードを所有できるようになりました。 _HomingLandmine_を取得します。今を除いて、ホーミングミサイルとランドマインの両方がホーミングクラスから拡張されるべきであると主張することができます。
ここで何かが足りないと思います。 Afaik、「コンポーネントの動作」ノードを作成する適切な方法は、それ自体を変更せず、デフォルトのターゲットが親である「ターゲット」ノードを直接変更する方法です。 私が間違っていなければ、これはあなたが直面している問題を完全に回避します。
extends Node
var src_target
export(NodePath) onready var dst_target = get_node(dst_target) if dst_target else null
func _notification(p_what):
match p_what:
NOTIFICATION_PARENTED:
src_target = get_parent()
NOTIFICATION_UNPARENTED:
src_target = null
func _physics_process():
# if necessary, can manually assign src_target elsewhere to be NOT a parent
if src_target and src_target is KinematicBody2D:
src_target.move_and_slide(...) # do logic to get parameters that move towards dst_target
このようなことは、スクリプトを使用してノードを「ホーミング」機能の子にするだけで、何も変更する必要がないことを意味します。 エクスポートされたプロパティ値を(シーン内または実行時に)割り当てて、何をホームにするかを指示するだけです。 他のエクスポートされたプロパティを使用して、移動のタイプを変更できます。また、異なる「ビルド」が必要な場合は、そのプロパティをリソースにアウトソーシングすることもできます。 繰り返しになりますが、Godotを使用すると、ゲームフレームワークの設計に非常に柔軟に対応できます。
いくつかの修正:
- C#
- - public class Burning {};
+ - public class Burning {}
- using Game.Burning;
- Burning.apply(wood, fire); // is it :: here? I forget...
- - Burning b = Burning::GetSingleton(); b.apply(wood, fire);
+ - Burning b = Burning.GetSingleton(); b.apply(wood, fire);
クラスの閉じ中括弧の後のセミコロンは必要ありません。 ::
の代わりに、静的メンバーにドットを使用します。
ちなみに、シングルトンにアクセスするための規則は、メソッドの代わりにプロパティ(一般にInstance
という名前)を使用することです。
@neikeqありがとう。 私はC#で練習しすぎています、笑。
「グローバルスクリプト」アプローチに関しては、私はこれに非常に反対です。 それは開発者が彼らのゲームを悪い方法でコーディングすることを奨励するでしょう。 以前のベアC ++およびJavaゲーム開発者がUnity / Unreal / Godot / etcを試したときによくある質問は、「コードを記述できるメインのゲームループはどこにあるのか」です。 このようなシステムを追加すると、開発者はこれを実行できるようになるため、オブジェクトでスクリプトを使用するだけでなく、変更するオブジェクトを参照するグローバルスクリプトでコードを記述してしまう可能性があります。
おそらく代わりに、ベアボーンNode
ノードのパフォーマンスを改善して、純粋にスクリプトを保持するオブジェクト「コンポーネント」のオーバーヘッドを発生させないようにすることができます。 あるいは、別の単純な「only-holds-scripts」ノードでさえあるかもしれません。
@aaronfranke
「グローバルスクリプト」アプローチに関しては、私はこれに非常に反対です。 それは開発者が彼らのゲームを悪い方法でコーディングすることを奨励するでしょう。 以前のベアC ++およびJavaゲーム開発者がUnity / Unreal / Godot / etcを試したときによくある質問は、「コードを記述できるメインのゲームループはどこにあるのか」です。
私が述べたように、誰かがこれを行うことを嫌う場合(大規模なプロジェクトでは合理的にそうです)、API階層をさらに下に移動する他のスクリプトの定数を維持する「名前空間」グローバルスクリプトクラスを作成するだけで問題はありません。 ここでは、実際のノード参照ではなく、スクリプトについてのみ説明しています。
このようなシステムを追加すると、開発者はこれを実行できるようになるため、オブジェクトでスクリプトを使用するだけでなく、変更するオブジェクトを参照するグローバルスクリプトでコードを記述してしまう可能性があります。
このシステムは、Autoloadsを介してGodotの誰でもすでに実装可能です(提案されている機能の「追加」はありません)。 さらに、彼らが最初に直面している問題は、彼らが持っているので、彼らがシステム自体をサブノードとして世界に追加したくないということです(私はそれについてもフォローアップコメントで提案しますが)そこにノードとそのノード上のスクリプトの両方を配置し、後で物事が動き回らなければならないことに気付いたときに、すべてのノードとスクリプトの間の関係をリファクタリングする可能性があります。
おそらく代わりに、スクリプトを純粋に保持するオブジェクト「コンポーネント」のオーバーヘッドを導入しないように、ベアボーンノードノードのパフォーマンスを改善することができます。
どのように? これを透過的に行う唯一の方法は、MultiScriptシステムを実装することであり、そのパラダイムに伴う多くの問題があります。 その問題を解決しようとしたときに思いついた他の唯一の選択肢は、#23101で提案したGDScript特性システムでした。これは、MultiScriptの問題を1つの言語に限定しますが、さらに深刻な問題が多数あります。
あるいは、別の単純な「only-holds-scripts」ノードでさえあるかもしれません。
3.2で配列型ヒントシステムを修正すると、これを行うことができるようになります...
extends Node
export(Array, Script) behaviors = []
辞書(名前でスクリプトにアクセスするため)と3.1のEditorInspectorPluginを使用して機能を実装し、これらのノードがインスペクターで開かれたときにカスタムUIを定義することもできます(スクリプトのエクスポートされた配列UIを作成しますが、内部のファイル名と一致するキーを使用してスクリプトを追加します)。
リソース#burning.gdを拡張します
ああ、私は私たちの問題を見つけたと思います。 プリロードの試行はいずれもリソースから拡張されていませんでした。 カスタムリソースを作成できることすら知らなかったと思います。
また、ゲームを私たちと共有したり、ワークフローを説明したりした人は、リソースから拡張されていなかったことも指摘したいと思います。
ほとんどの人がノードを拡張していました。 これがどれほどの違いを生むかはわかりませんが、テストを実行する必要があります。
FileSystemItemList(警告、これは初期のWIPです)
間違いなくこれを確認する必要があります。
@MysteryGM
カスタムリソースを作成できることすら知らなかったと思います。
はい! 最近、プロセスの概要を説明するセクションをドキュメントに追加しました。 :-D
オブジェクト、参照、リソース、そしてもちろんノード(またはこれらのクラスの派生物)を含む任意のエンジンタイプをスクリプトで拡張できます。 拡張できないのは、エンジンとエディターのシングルトン(OS、Engine、EditorFileSystemなど)だけです。
トピックへのご意見ありがとうございます。 継承の問題は、クラスを実装するときにクラスのすべての関係を知っている場合にのみ機能することです。
どういたしまして。 薪システムの実装には必要ないので、コメントの最後に継承を入れました。
慣れ親しんだパラダイムを使って解決策を考えているようですが、問題は薪システムの作り方ではなく、好きなパラダイムの使い方です。
それではお詫び申し上げます。 私はGDScriptの継承に精通していませんが、他の人がすでにあなたの質問に答えていると思います。
OK、新しいメソッドをテストする時間があり、完全に機能することがわかりました。 すでに何百ものノードをスクリプトに置き換えることができます。 パフォーマンスが大幅に向上します。
リソースのプリロードによって、スクリプトを含めるという問題が解決されることを考慮してください。 GDscriptでリソース変数をエクスポートすることにより、UnityのMultiScriptとScriptableObjectの両方の代わりに使用することもできます。
リソースをより詳細に説明するためにドキュメントが更新されたという事実と組み合わせて。
言うまでもなく、Godot 3.1には、さらに多くのワークフローを可能にするスクリプトクラスもあります。
この問題の当初の目標は解決されたと思いますが、この問題を解決できるようになりましたか?
繰り返しになりますが、ディスカッションに参加してくれたすべての人に感謝します。特に、Godotエンジンについて膨大な洞察を提供してくれた@willnationsdevに感謝します。
@MysteryGMこのスレッドの開始時と終了時のあなたの考えは、ブログやgodot-docsドラフトに書くのが良いと思います。 ほとんどの初期のユーザーは、複雑なスクリプト編成を実現しようとするとパフォーマンスの間違いを犯すことが多いと思います。学習の観点から、「前」と「後」の適切な記述が必要です。 初期のチュートリアルで学んだレッスンとパターンは、大規模なゲームにうまく変換されません。つまり、大規模なレッスンについては、より多くのブログやアドバイスが必要です。
@pgruenbacher 、それは素晴らしいアイデアです。 私たちのチームには2つの問題があります。1つは英語を有用なレベルまで知っている2人だけであり、2つ目は時間がかかることです。
それでも、開発ブログを作成するという良い変更があり、発見したすべてのものをメモしておきます。 「TransitiontoGodot」のブログエントリを作成する可能性があります。
チームにフリーランサーを雇いたいので、今は「アーティストのためのGodotクラッシュコース」のPDFチュートリアルに取り組んでいますが、Godotはまだよく知られていません。
これらのチュートリアルは、Godotをプロのゲームアーティストに紹介することを目的としています。
これらを完了したら、他のGodotユーザーと共有します。学習中は間違いを修正する方が簡単なので、最初はPDFのままにしておきます。
@pgruenbacher @MysteryGM Godotの前後の経験と同じではありませんが、この問題といくつかの関連する繰り返しの質問により、godot-docsのシーン/スクリプトデザインのベストプラクティスの記事に取り組み始めるようになりました。 フォークにブランチがありますが、それは非常に初期のWIPATMです。
このようなトピックを読むことは非常にがっかりします(適切なエンジンを選択したかどうかをもう一度推測するという意味で)。 私たちのプロジェクトは15,000LoCをはるかに超えており、完璧に編成されており、優れたパフォーマンスを発揮します。 (ここにいる他の人は私よりはるかに賢いので、特定のポイントの詳細には立ち入りません)。
そうは言っても、Godot、MysteryGMと一緒にいてくれてうれしいです! Defは開発ブログを読むのを楽しみにしています
私の意見では、重要なロジックを備えたゲームは、コードを使用した方が良いと思います
とにかくゲームエンジンから分離されているので、どのように問題になるべきではありません
エンジンは作動します。 私のノードスクリプトは主にインターフェイスのレンダリングに使用されます
と物理学の論理。 ゲームロジックは、個別にコンパイルされた共有ライブラリです
2018年11月14日水曜日、Aaron-Fleishernotifications @ github.com
書きました:
このようなトピックを読むことは非常に落胆します(
適切なエンジンを選択したかどうかを再確認させてください)。 私たちのプロジェクトは順調です
15,000以上のLoCがあり、完璧に整理されており、優れたパフォーマンスを発揮します。 (私は行くつもりはない
ここの他の人々ははるかに賢いので、特定のポイントの詳細に
私より)。
そうは言っても、Godot、MysteryGMと一緒にいてくれてうれしいです! デフ探し
開発ブログを読むことを楽しみにしてください—
あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/godotengine/godot/issues/23052#issuecomment-438871197 、
またはスレッドをミュートします
https://github.com/notifications/unsubscribe-auth/ADLZ9pw2-G0kE19meyi7iSkceAldfAMjks5uvLb4gaJpZM4XelSe
。
@ Aaron-Fleisher
...適切なエンジンを選択したかどうかを2番目に推測します
現在使用しているエンジンが機能している場合は、何らかの回避策を講じる必要がある場合でも、心配する必要はありません。 一部のプレイヤー(または他の開発者)があなたの能力/正気を疑問視するかもしれませんが、それはゲーム開発の現実にすぎません。 多くの熱心な人々が見かけの権限で話します(多くの場合、実際のスキルレベルをはるかに上回っています)。
あなたはあなたの問題を知っている人であり、あなたは仕事をしなければならない人です。 おそらくさらに10%〜20%の生産性を購入したであろうものによって麻痺することを避けてください。 次のゲームのためにそれを保存します。 または、あなたがすでに知っているツールを学ぶことにすでにたくさんの投資をしているので、そうしないでください。 あなたの選択 :)
わからないけど、Godotの開発者は自分たちが何をしているのかわからないような気がする。
Godot 3.0.6安定版を最初に使用すると、醜い、機能不全の「プロジェクトマネージャー」が表示されます。 それがどのように機能するかを理解することさえできるとき(そしてそれはまったく直感的ではありません)、アセットライブラリからサンプルプログラムをダウンロードしようとするたびにアプリがクラッシュします。 時々、アプリはただ応答を停止します。 時々、アプリは不思議な「条件!接続が真です」エラーをスローします。 時々、ダウンロードは行き詰まります。 そして毎回、100MBのファイルはほとんどダウンロードするのに約10分かかりますが、私は同じ時間で他の場所に10GBをダウンロードできます。 「再試行」は、ダウンロード全体を最初から開始します。
ここでの「安定」とは「毎回確実に台無しになる」という意味だと感じています。
圧倒的な第一印象について話してください。
@dejaycそれは奇妙です。 Windows10またはLinuxMintデバイスのプロジェクトマネージャー(3.0.6安定版またはマスターブランチでさえ)で問題が発生したことはありません。 ここで問題に関する新しい問題を作成することをお勧めします(これはそのようなトピックには実際には適切な問題ではないため)。誰かがより良い支援を提供できることを願っています。
@dejayc
私たち全員がPatreonに寄付すれば、Godotプロジェクトはフルタイムのユーザビリティ担当者を雇うことができます。
私はあなたのマイナーな点に同意しますが、エンジンはソーシャルメディアのマーケティング投稿に基づいて特定のプロジェクトの欠点がどれほど重大であるかに基づいて選択する必要があります。 そして悲しいことに、それらのすべてには、UIの表面レベルよりも深い_多くの_欠点があります...
そうは言っても、私はプロジェクトマネージャーについての提案の問題を開きました。自由な時間が与えられたので、この分野でいくつかの改善に取り組むつもりです。
私はUnityとGodotの両方で作業し、Godotの一般的なワークフローと構造がはるかに優れていて直感的であることがわかりました(特に、Unityのシーン/プレハブの代わりにシーンモデル、複数のコンポーネントの代わりに「シングルスクリプト」モデル、速度エンジンをダウンロード/起動してエクスポートするとき、および完全にオフラインで動作する機能)。
両方に可能なワークフローとモデルがたくさんあり、どちらが自分に適しているかを簡単に判断することはできません。
最も参考になるコメント
質問が単純に「Godotで同じ結果を達成する方法はいくつかありますか?」である場合、答えは「はい」です。 また、ゲーム内の各システムには異なる要件がある可能性があるため、単一のワークフローを強制しようとするのはばかげています。 多くのパフォーマンスを必要とし、ゲームデザイナーが頻繁に更新する必要があるシステムと同じ方法でコーディングすることはできません。 すべてのソリューションにはトレードオフがあるため、「公式」ワークフローを作成する意味はありません。