私はシンプルなゲームマネージャーを作っています。ゲーム内のすべてのシーンからアクセスできるスクリプトがあります。そして、新しいシーンをロードした後、変数の値を確認する必要があります。しかし、このスクリプトを含むオブジェクトがすべてのシーンに存在する間、私のコードはシミュレーションを開始した後に一度だけ実行されます。なにが問題ですか?新しいシーンを読み込んだ後に機能しないのはなぜですか?
Unityにプリロードシーン「ビルトイン」がないのは非常に紛らわしいです。
彼らは将来この概念を追加します。
繰り返すには、文字通りプリロードシーンが必要です。
とても簡単です。
幸いなことに、プリロードシーンは非常に簡単です。
ステップ1。
「preload」という名前のシーンを作成します。 Build Managerのscene 0でなければなりません。
ステップ2。
「プリロード」シーンで、「__ app」などと呼ばれる空のGameObjectを作成します。
単に、「__ app」にDontDestroyOnLoad
を付けます。
注意:
これはプロジェクト全体の唯一の場所DontDestroyOnLoad
を使用します。
とても簡単です。
例では、開発者は1行のDDOLスクリプトを作成しました。
そのスクリプトを「__app」オブジェクトに配置します。
DDOLについて再度考える必要はありません。
ステップ3
アプリには(多くの)「一般的な動作」があります。そのため、データベース接続、効果音、スコアリングなどのようなもの。
一般的な動作を「_app」に配置する必要があります。
本当に簡単です。
一般的な動作は-もちろん-プロジェクトのどこでも、常に、すべてのシーンで利用可能です。
他にどのようにそれを行うことができますか?
上の画像の例では、「Iap」(「アプリ内購入」)などに注目してください。
すべての「一般的に必要な動作」-サウンドエフェクト、スコアリングなど-は、そのオブジェクト上にあります。
これは-もちろん、当然-
他のすべてのゲームオブジェクトで使用するUnityの通常の機能をすべて使用できます。
もちろん、通常のInspector変数(ドラッグして接続)、設定などを使用できます。
(実際、既存のプロジェクトで作業するために雇われたとしましょう。最初に行うことは、プリロードシーンを一目見ることです。プロジェクトのすべての「一般的な動作」を1か所で見ることができます。 、スコアリング、AIなど。これらのもののすべての設定は、インスペクター変数としてすぐに表示されます...スピーチボリューム、プレイストアIDなど)。
「サウンド効果」の一般的な動作の例を次に示します。
「ボイスオーバー」の一般的な行動と「音楽」の一般的な行動もあるようです。
繰り返す。 「一般的な行動」について。 (効果音、スコアリング、ソーシャルなど)これらは、事前ロードシーンのゲームオブジェクトでのみ使用できます。
できました。
正直言ってそんなに簡単です。
文字通り何もありません!
他の環境から来た多くのエンジニアはこれに追いつきます。なぜなら、それは「簡単ではない」ように思えるからです。
繰り返しますが、全体的な問題は、(奇妙なことに)Unityがプリロードシーンを "ビルドイン"するのを忘れたことです。したがって、クリックしてプリロードシーンを追加するだけです。プリロードシーンにDDOLを追加することを忘れないでください。
したがって、開発中:
常にプリロードシーンからゲームを開始します。
とても簡単です。
(重要な点:あなたのアプリは確かに「早い」シーンを持っています。例えば、「スプラッシュスクリーン」や「メニュー」。あなたはできませんプリロードシーンとして「スプラッシュスクリーン」または「メニュー」を使用します。文字通り"プリロードシーン"。プリロードシーンはthen loadスプラッシュシーン、メニューシーン、その他あなたが望む。)
プリロードシーンがあります。
「一般的な動作」はすべて、単にプリロードシーンにあります。
次に、 "SoundEffects"または "GameManager"と言う問題を簡単に見つけることができます。
あらゆるシーンのあらゆるゲームオブジェクトのスクリプトから、それらを簡単に見つけられる必要があります。
Sound sound = Object.FindObjectOfType<Sound>();
Game game = Object.FindObjectOfType<Game>();
必要なスクリプトについては、Awake
で実行してください。
正直言ってそんなに簡単です。これですべてです。
Sound sound = Object.FindObjectOfType<Sound>();
オンラインで見られるabsolutely wrongのコード例が何百もあるため、大きな混乱が生じています。また、新しいUnityエンジニアは「信じられない」ほど簡単です!
これは本当に簡単です-正直です!
Unityが組み込みの「プリロードシーン」を追加するのを忘れたのはまったく奇妙です。SoundEffects、GameManagerなどのシステムを接続する場所です。Unityの奇妙なことの1つにすぎません。したがって、Unityプロジェクトで最初に行うことは、1回クリックするだけでプリロードシーンを作成することです。
それでおしまい!
もっと少ない(!)行のコードを本当に入力したい場合は、非常に簡単です-これらのそれぞれに対して単にグローバルを使用できることに注意してください!
これについて詳しく説明します here (私の人気のあるGrid.csスクリプトを使用できます)および以下の@Fritsの回答で。
(グローバルを使用するか、特定のコンポーネントを必要とする各コンポーネントにローカル変数があるかは、コードスタイルの問題です。非常にまれな状況では、「グローバル」アプローチが(グローバルと同様に)実行可能です。
DylanBからの質問:(開発中「再生」をクリックする前に毎回プリロードシーンをクリックする必要があるのは非常に面倒です「これは自動化できますか?」
もちろん、すべてのチームはこれを行うための異なる方法を持っています。簡単な例を次に示します。
// this should run absolutely first; use script-execution-order to do so.
// (of course, normally never use the script-execution-order feature,
// this is an unusual case, just for development.)
...
public class DevPreload:MonoBehaviour
{
void Awake()
{
GameObject check = GameObject.Find("__app");
if (check==null)
{ UnityEngine.SceneManagement.SceneManager.LoadScene("_preload"); }
}
}
しかし、忘れないでください:「他に何ができますか?」 ゲームはプレロードシーンから開始する必要があります。プレロードシーンに移動する以外に、他にできることは何ですかゲーム? 「Unityを実行するためにUnityを起動するのは面倒です-Unityの起動を回避する方法は?」と尋ねることもできます。ゲームはもちろん、絶対にプリロードシーンから開始する必要があります。確かに、Unityで作業するときは、「Playをクリックする前にプリロードシーンをクリックする」必要があります。
@Fattie:これをすべて詳しく説明してくれてありがとう、素晴らしい!ただし、人々があなたに到達しようとしているという点があります。私もそれを試してみます:
モバイルゲームのすべてのインスタンス化で、すべての「グローバルクラス」ごとに「FindObjectOfType」を実行することは望ましくありません。
代わりに、静的/シングルトンのインスタンス化を、それを探すことなくすぐに使用させることができます!
そして、それはこれと同じくらい簡単です:どこからでもアクセスしたいクラスでこれを書いてください。XXXXXはクラスの名前です。
public static XXXXX Instance { get; private set; }
void Awake()
{
if (Instance == null) { Instance = this; } else { Debug.Log("Warning: multiple " + this + " in scene!"); }
}
今あなたの例の代わりに
Sound sound = Object.FindObjectOfType<Sound>();
見ずに、余分な変数を使用せずに、単にこのように使用するだけで、どこからでもすぐに使用できます。
Sound.Instance.someWickedFunction();
代わりに(技術的には同一)、通常はグリッドと呼ばれる1つのグローバルクラスを使用して、それぞれを「保持」します。 Howto 。そう、
Grid.sound.someWickedFunction();
Grid.networking.blah();
Grid.ai.blah();
好きなシーンを開始し、Unity Editorで再生ボタンを押すたびに_preloadシーンを再統合する方法を次に示します。 Unity 2017 RuntimeInitializeOnLoadMethod
以降に利用可能な新しい属性があります。詳細は こちら です。
基本的に、単純なプレーンc#クラスと、RuntimeInitializeOnLoadMethod
を含む静的メソッドがあります。これで、ゲームを開始するたびに、このメソッドはプリロードシーンをロードします。
using UnityEngine;
using UnityEngine.SceneManagement;
public class LoadingSceneIntegration {
#if UNITY_EDITOR
public static int otherScene = -2;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void InitLoadingScene()
{
Debug.Log("InitLoadingScene()");
int sceneIndex = SceneManager.GetActiveScene().buildIndex;
if (sceneIndex == 0) return;
Debug.Log("Loading _preload scene");
otherScene = sceneIndex;
//make sure your _preload scene is the first in scene build list
SceneManager.LoadScene(0);
}
#endif
}
次に、_preloadシーンに、(開始した場所から)目的のシーンをロードバックする別のスクリプトがあります。
...
#if UNITY_EDITOR
private void Awake()
{
if (LoadingSceneIntegration.otherScene > 0)
{
Debug.Log("Returning again to the scene: " + LoadingSceneIntegration.otherScene);
SceneManager.LoadScene(LoadingSceneIntegration.otherScene);
}
}
#endif
...