ホームページ > テクノロジー周辺機器 > IT業界 > Unity 5の保存とロード機能のマスタリング5

Unity 5の保存とロード機能のマスタリング5

Joseph Gordon-Levitt
リリース: 2025-02-19 09:21:10
オリジナル
391 人が閲覧しました

Unity 5の保存とロード機能のマスタリング5

この記事のレビューを査読してくれたVincent Quarlesに感謝します。 このチュートリアルでは、ゲームの保存とロード機能の実装を終了します。プレイヤーゲームデータの拡張に関する以前のチュートリアルでは、統計や在庫などのプレーヤー関連データを保存およびロードしたことに成功しましたが、今では最も困難な部分である世界オブジェクトに取り組みます。最終的なシステムは、長老のスクロールゲームを連想させる必要があります。すべてのオブジェクトは、無期限に保存されています。

練習するためにプロジェクトが必要な場合は、最後のチュートリアルで完了したプロジェクトのバージョンを次に示します。 1つのポーションと1つの剣のアイテムを生成するゲーム内の相互作用可能なオブジェクトでアップグレードされました。それらを生み出すことができ、


> spawned)を拾うことができ、状態を正しく保存してロードする必要があります。プロジェクトの完成バージョン(Save Systemを完全に実装した)は、この記事の下部にあります。 プロジェクトの開始ファイルをダウンロード

プロジェクトGithubページ

プロジェクトzipダウンロード


キーテイクアウト


デリゲートイベントシステムを利用して、オブジェクトに状態を保存する時期に通知し、保存/負荷システムのモジュール性と柔軟性を高めます。

レベルマスターオブジェクトを実装して、オブジェクトの産卵とdepawningを管理し、世界のオブジェクトがゲームセッション全体で状態を維持することを保証します。
    シリアル化可能なクラスを使用して、さまざまな種類のオブジェクトに対して簡単に拡張または変更できる位置などのオブジェクトプロパティを保存します。
  • オブジェクトスクリプト内のイベントを保存するための適切なサブスクリプションとunsubscriptionを確認して、エラーを回避し、ゲーム状態を効果的に管理します。
  • 複雑なデータ構造を処理し、データの整合性を確保するために、バイナリフォーマットを使用して保存およびロードするための堅牢なシステムを開発します。
  • システムをテストおよび拡張して、新しいオブジェクトの種類と機能を含め、さまざまなゲーム開発ニーズに合わせてシステムの適応性とスケーラビリティを実証します。
  • 実装理論
  • オブジェクトを実装する前に、オブジェクトを保存およびロードするシステムを分解する必要があります。何よりもまず、オブジェクトを生成してデスポーンする何らかのレベルマスター
  • オブジェクトが必要です。レベルに保存されたオブジェクトをスポーンする必要があります(レベルをロードして新たに起動していない場合)、デパーンオブジェクトを拾い上げ、オブジェクトに自分自身を保存する必要があることを通知し、オブジェクトのリストを管理する必要があります。たくさん聞こえますが、それをフローチャートに入れましょう:
  • 基本的に、ロジック全体がオブジェクトのリストをハードドライブに保存しています。これは、次にレベルがロードされると、移動し、プレイを開始するとすべてのオブジェクトが生成されます。簡単に聞こえますが、悪魔は詳細にあります:どのオブジェクトを保存するオブジェクトをどのようにして、どのようにしてそれらを引き戻すことができますか?

    代表者とイベント

    前の記事では、自分自身を保存するために必要なオブジェクトに通知するために、デリゲートイベントシステムを使用する予定であると述べました。最初に、代表者とイベントが何であるかを説明しましょう

    公式の代表団のドキュメントと公式イベントのドキュメントを読むことができます。しかし、心配しないでください:公式文書のテクノバブルの多くを理解していないので、私はそれを平易な英語に入れます:

    Delegate

    代表者を関数の青写真と考えることができます。関数がどのように見えるかを説明しています:その返品タイプとは何か、そしてそれが受け入れる議論。たとえば、

    この代表者は、何も返されない関数(void)を記述し、.NET/Monoフレームワークの2つの標準引数を受け入れます。イベントの送信者を表す一般的なオブジェクトと、さまざまなデータを渡すために使用できる最終的な引数です。あなたは本当にこれについて心配する必要はありません、私たちは議論として(null、null)に合格することができますが、彼らはそこにいなければなりません。
public delegate void SaveDelegate(object sender, EventArgs args);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

では、これはイベントとどのように結びついていますか?

イベント

イベントは、関数の

ボックスと考えることができます

。デリゲート(青写真)に一致する関数のみを受け入れ、実行時に機能を配置および削除できます。 その後、いつでもイベントをトリガーできます。つまり、現在ボックスにあるすべての機能を一度に実行することを意味します。次のイベント宣言を検討してください この構文は次のように述べています:パブリックイベントを宣言します(誰でも購読できます - 後で説明します)。

購読して登録解除

イベントへの購読は、基本的に「ボックスに関数を置く」ことを意味します。構文は非常に簡単です。私たちのイベントがよく知られているGlobalObjectクラスで宣言されており、イベントに登録する必要がある

potiondroppable
public event SaveDelegate SaveEvent;
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
という名前のポーションオブジェクトクラスがあるとしましょう。

ここで構文を説明しましょう。最初に、説明された委任標準に適合する関数が必要です。オブジェクトのスクリプトには、SaveFunctionという名前のこのような関数があります。後で自分で書きますが、今のところ、オブジェクトをハードドライブに保存するための機能機能であると仮定して、後でロードできます。

それがあるとき、私たちは単にその関数を開始時にボックスに入れたり、スクリプトを覚醒させたり、破壊したときに削除したりします。 (登録解除は非常に重要です:破壊されたオブジェクトの関数を呼び出すと、実行時にNULL参照例外が得られます)。宣言されたイベントオブジェクトにアクセスし、追加演算子を使用して機能名を使用してこれを行います。

注:ブラケットや引数を使用して関数を呼び出していません。関数の名前を使用しているだけです。他に何も使用していません

それでは、ゲームのフローの例で最終的にこれが何をするか説明しましょう。

ロジックフロー

ゲームの流れを通して、プレイヤーの行動が世界に2つの剣と2つのポーションを生み出したと仮定しましょう(たとえば、プレーヤーは戦利品で胸を開けました)。

これらの4つのオブジェクトは、セーブイベントで機能を登録します。

次に、プレイヤーが世界から1つの剣と1つのポーションを拾うと仮定しましょう。オブジェクトが「ピックアップ」されると、彼らはプレーヤーの在庫の変化を効果的にトリガーし、それから自分自身を破壊します(魔法を台無しにします、私は知っています):Unity 5の保存とロード機能のマスタリング5

そして、プレイヤーがゲームを保存することにしたとしましょう。たぶん、彼らは本当に3回鳴ったその電話に答える必要があるかもしれません(ねえ、あなたは素晴らしいゲームを作りました):Unity 5の保存とロード機能のマスタリング5

基本的に、ボックス内の関数が1つずつトリガーされ、すべての機能が完了するまでゲームはどこにも行かないということです。 「自らを保存する」すべてのオブジェクトは、基本的にリストに自体を書き留めています。次のゲームロードでは、レベルマスターオブジェクトによって検査され、リストにあるすべてのオブジェクトがインスタンス化されます(スポーン)。それだけです。これまでのところ、これまでの記事に従っていたら、基本的にすぐに実装を開始する準備ができています。それにもかかわらず、私たちはここでいくつかの具体的なコードの例に行きます、そしていつものように、あなたが記事の最後にあなたを待っている完成したプロジェクトがあなたが全体がどのように見えるかを見たいならあなたを待っています。 Unity 5の保存とロード機能のマスタリング5code

最初に既存のプロジェクトを進めて、すでに中にあるものに慣れてみましょう。

ご覧のとおり、既に述べた2つのオブジェクトのスポーナーとして機能するこれらの美しく設計されたボックスがあります。 2つのシーンのそれぞれにペアがあります。すぐに問題を見ることができます。シーンを移行したり、

f5/f9Unity 5の保存とロード機能のマスタリング5を使用して保存/負荷をかけたりすると、産卵したオブジェクトが消えます。

これ以上存在しません。ここでのタスクは次のとおりです

ポーションオブジェクトのリストを作成します

    剣のオブジェクトのリストを作成します
  • グローバルセーブイベントを実装してください
  • 保存関数を使用してイベントを購読します
  • レベルマスターオブジェクトを実装
  • ゲームをロードしている場合、レベルマスターをすべて保存したオブジェクトをすべてスポーンします。
  • あなたが見ることができるように、これはそのような基本的な機能がそうなることを望むほど些細なことではありません。実際、そこに既存のゲームエンジン(CryEngine、UDK、Unreal Engine 4、その他)は、実際に簡単な保存/負荷機能の実装を準備していません。これは、ご想像のとおり、メカニックを保存することは各ゲームに本当に固有であるためです。通常、保存する必要があるクラスをオブジェクトにするだけです。完成/アクティブなクエスト、派factの親しみやすさ/敵意、一部のゲームの現在の気象条件など、世界の状態です。それは非常に複雑になりますが、保存メカニックの適切な基盤により、より多くの機能を使用して簡単にアップグレードすることができます。
  • オブジェクトクラスリスト
  • 最初に簡単なもの、つまりオブジェクトリストを始めましょう。プレーヤーのデータは、Serializablesクラスのデータを簡単に表現して保存およびロードされます。

同様の方法で、オブジェクトを表すいくつかのシリアル化可能なクラスが必要です。それらを書くには、どのプロパティを保存する必要があるかを知る必要があります。プレイヤーには、保存するものがたくさんありました。幸いなことに、オブジェクトにとって、あなたは彼らの世界の地位以上のものを必要とすることはめったにありません。この例では、オブジェクトの位置を保存するだけで、他に何も保存する必要があります。

コードをうまく構成するために、シリアル化可能性の最後にある簡単なクラスから始めます。

なぜ私たちが基本クラスを使用しているのではないのか疑問に思うかもしれません。答えは、私たちができるということですが、節約が必要な特定のアイテムプロパティを追加または変更する必要があることを実際に知ることはありません。さらに、これはコードの読みやすさの方がはるかに簡単です

今では、私がUnity 5の保存とロード機能のマスタリング5droppable

という用語をたくさん使用していることに気付いたかもしれません。これは、ドロップ可能な(スポーン可能な)オブジェクトと配置可能なオブジェクトを区別する必要があるためです。後で説明します。

今、プレイヤーのデータとは異なり、実際にはいつでもプレーヤーが1人しかいないことがわかっているため、ポーションのような複数のオブジェクトを持つことができます。動的リストを作成し、このリストがどのシーンに属しているかを示す必要があります。レベル1でレベル2のオブジェクトをスポーンすることはできません。これは、Serializablesで再び簡単に行うことができます。これを最後のクラスの下に書いてください:

public delegate void SaveDelegate(object sender, EventArgs args);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

これらのリストのインスタンスを作成するのに最適な場所は、GlobalControlクラスです。

public event SaveDelegate SaveEvent;
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
私たちのリストは今のところ行くのがかなり良いです。レベルマスターオブジェクトからアイテムをスポーンする必要があるときにそれらにアクセスし、プレーヤーデータを既に行っているように、グローバルコントロール内からハードドライブから保存/ロード。

委任とイベント

ああ、最後に。有名なイベントのものを実装しましょう。

グローバルコントロールの

//In PotionDroppable's Start or Awake function:
GlobalObject.Instance.SaveEvent += SaveFunction;

//In PotionDroppable's OnDestroy() function:
GlobalObject.Instance.SaveEvent -= SaveFunction;

//[...]
public void SaveFunction (object sender, EventArgs args)
{
 //Here is code that saves this instance of an object.
}
ログイン後にコピー
ログイン後にコピー
ご覧のとおり、イベントを静的な参照にしているので、後でより論理的で作業しやすいです。 イベントの実装に関する最後のメモの1つ:イベント宣言を含むクラスのみがイベントを発射できます。誰でもGlobalControl.saveEvent = ...にアクセスすることでそれを購読できますが、SaveEvent(null、null); GlobalControl.SaveEvent(null、null)を使用しようとしています。他の場所からは、コンパイラエラー!

になります

そして、それはイベントの実装のためです!それにいくつかのものを購読しましょう!

イベントサブスクリプション

イベントが発生したので、オブジェクトはそれを購読する必要があります。つまり、イベントを聞き始めて、発射したときに反応する必要があります。

各オブジェクトに対して、イベントが発射されるときに実行される関数が必要です。 Pickups

フォルダーのPotionDropPableスクリプトにアクセスしましょう。注:Swordにはまだスクリプトが設定されていません。すぐにそれを作ります!

potiondroppableで、これを追加してください。 サブスクライブを正しく行い、イベントに登録解除しました。今、疑問が残っています、

このオブジェクトをリストに保存する方法、正確に?

最初に、現在のシーンの初期化されたオブジェクトのリストがあることを確認する必要があります。 GlobalControl.cs: この関数は、レベルごとに1回起動する必要があります。問題は、GlobalControlがレベルを通過し、その開始および目覚めの機能が1回だけ発射されることです。すぐに作成するレベルマスターオブジェクトからこの関数を呼び出すだけで、それを回避します。 現在のアクティブシーンリストも返すために、小さなヘルパー機能が必要になります。 GlobalControl.cs: 今、私たちは常にアイテムを保存するリストを持っていると確信しています。ポーションスクリプトに戻りましょう:

これは、すべての構文砂糖コーティングが本当に輝く場所です。これは非常に読みやすく、理解しやすく、必要なときに自分のニーズに合わせて変更しやすいです!要するに、新しい「ポーション」表現を作成し、実際のリストに保存します。

レベルマスターオブジェクトの作成

最初に、少しの準備。既存のプロジェクトには、シーンがロードされているかどうかを示すグローバル変数があります。しかし、ドアを使用してシーンが

に移行されているかどうかを示すような変数はありません。前の部屋に戻っても、その間にゲームを保存/ロードしなかったとしても、すべてのドロップされたオブジェクトがまだそこにあることを期待しています。

それを行うには、グローバルコントロールに小さな変更を加える必要があります:
public delegate void SaveDelegate(object sender, EventArgs args);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

transitionScript:

public event SaveDelegate SaveEvent;
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

正常に機能するレベルマスターオブジェクトを作成する準備ができています。

これで、リストを読み取り、ゲームをロードしているときにオブジェクトをスポーンするだけです。これは、レベルマスターオブジェクトが行うことです。新しいスクリプトを作成して、

levelmasterと呼びましょう

//In PotionDroppable's Start or Awake function:
GlobalObject.Instance.SaveEvent += SaveFunction;

//In PotionDroppable's OnDestroy() function:
GlobalObject.Instance.SaveEvent -= SaveFunction;

//[...]
public void SaveFunction (object sender, EventArgs args)
{
 //Here is code that saves this instance of an object.
}
ログイン後にコピー
ログイン後にコピー
それはたくさんのコードなので、それを分解しましょう。

コードは開始時にのみ実行され、必要に応じてGlobalControlの保存されたリストを初期化するために使用します。次に、シーンを読み込んだり移行したりするかどうかをGlobalControlに尋ねます。新しいゲームなどのシーンを新たに開始している場合、それは問題ではありません。オブジェクトはありません。

シーンの読み込みがある場合、保存されたオブジェクトのリストのローカルコピーを取得する必要があります(GlobalControl、

の繰り返しアクセスでパフォーマンスを少し保存するために構文をより読みやすくするため)。 次に、リストを通過し、すべてのポーションオブジェクトを内部に出現させます。産卵の正確な構文は、基本的にインスタンスメソッドオーバーロードの1つです。インスタンス化メソッドの結果をgameObject (何らかの理由で、デフォルトのリターンタイプは単純なオブジェクトです)にキャストする必要があります。これにより、変換にアクセスして位置を変更できます。

これは、オブジェクトが生成される場所です。スポーン時に他の値を変更する必要がある場合、これはそれを行う場所です。

各シーンにレベルマスターを置き、有効なプレハブを割り当てる必要があります。

重要な作品は1つだけありません。実際にイベントを起動し、リストをハードドライブまでシリアル化して読み取る必要があります。 GlobalControlの既存の保存および負荷関数でそれを行うだけです:

これも多くのコードがあるように見えますが、その大部分はすでにそこにありました。 (私の以前のチュートリアルに従えば、バイナリシリアル化コマンドを認識します。ここでの新しいものはFireSaveEvent関数とリストを保存する1つの追加ファイルです。

初期テストUnity 5の保存とロード機能のマスタリング5

プロジェクトを今すぐ実行すると、ポーションオブジェクトが正しく保存されてロードされます

f5

および
[Serializable]
public class SavedDroppablePotion
{
    public float PositionX, PositionY, PositionZ;
}

[Serializable]
public class SavedDroppableSword
{
    public float PositionX, PositionY, PositionZ;
}
ログイン後にコピー
f9

にヒットするか、ドアを通り抜けます(および任意の組み合わせの組み合わせそのような)。

しかし、もう1つ解決すべき問題があります。剣を保存していません。

これは、新しい

それでは、すでに新しいオブジェクト産卵システムが整っているとしましょう。すでに剣のオブジェクトを使用しているように。現在、それらは相互作用可能ではないので(基本的な物理学を超えて)、剣を「ピックアップ」して正しく保存できるようにするために、Potion Oneに似たスクリプトを書く必要があります。

現在生成されている剣のプレハブは、Assets> Prefabsフォルダーにあります。

それを機能させましょう。 Assets> Scripts> Pickupsに移動すると、potiondroppable

スクリプトが表示されます。その隣に、新しいSwordDropPableスクリプトを作成します:

「インタラクティブ」インターフェイスの実装を忘れないでください。それは非常に重要です。それがなければ、あなたの剣はカメラレイキャストによって認識されず、逆効果のままです。また、剣のプレハブがアイテムレイヤーに属していることを再確認してください。それ以外の場合は、Raycastによって再び無視されます。次に、このスクリプトをSword Prefabの最初の子供に追加します(実際にはメッシュレンダラーとその他のコンポーネントがあります):

public delegate void SaveDelegate(object sender, EventArgs args);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

さて、それらを生成する必要があります。レベルマスターでは、ポーションを生成するループのために私たちのために:

Unity 5の保存とロード機能のマスタリング5

…そしてそれだけです。新しいアイテムタイプを保存する必要があるときはいつでも:

public event SaveDelegate SaveEvent;
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
serializablesクラス

を追加します

イベントを保存するためにサブスクライブするアイテムのスクリプトを作成します
  • レベルマスターにインスタンスロジックを追加します。
  • 結論
  • 今のところ、システムは非常に粗雑です。ハードドライブに複数の保存ファイルがあり、オブジェクトの回転は保存されません(剣、プレイヤーなど)、シーンの移行中にプレーヤーを配置するためのロジック(ただし、そうではありません(読み込み)は少し風変わりです。

これらはすべて、ソリッドシステムが整ったら解決するための小さな問題です。このチュートリアルと完成したプロジェクトをいじくり回して、システムを改善できるかどうかを確認することをお勧めします。

でも、ゲームでセーブ/ロードメカニックを行うための非常に信頼性の高い堅実な方法ですが、これらの

例とは

とは異なる場合があります。

約束されているように、参照のために必要な場合、またはどこかに立ち往生したために、完成したプロジェクトが完成しました。保存システムは、このチュートリアルの指示と同じ命名スキームで実装されます。

完成したプロジェクトをダウンロード:

Project Githubページ
プロジェクトzipダウンロード
Unityの保存とロード機能の習得に関するよくある質問(FAQ)

Unity 5に保存システムを実装する最良の方法は何ですか?

Unity 5に保存システムを実装する最良の方法は、PlayerPrefsクラスを使用することです。 PlayerPrefsは、ゲームセッション間でデータを保存および取得する簡単な方法です。これにより、整数、フロート、文字列の形でデータを保存およびロードできます。ただし、PlayerPrefsは安全ではなく、機密データに使用されるべきではないことに注意することが重要です。より複雑なデータまたは安全なデータについては、バイナリフォーマッターまたはJSONシリアナーの使用を検討することをお勧めします。 Unityでは、PlayerPrefs、JSON Serialization、またはバイナリフォーマットを使用して5を実現できます。 PlayerPrefsは最も簡単な方法であり、整数、フロート、文字列を保存およびロードできます。 JSONのシリアル化はもう少し複雑ですが、より柔軟性とセキュリティを可能にします。バイナリフォーマットは最も安全な方法ですが、最も複雑です。

実行順序は、Unity 5の保存および負荷機能にどのように影響しますか?どのスクリプトが実行されますか。これは、保存およびロード機能に大きな影響を与える可能性があります。たとえば、データをロードするスクリプトがデータを保存するスクリプトの前に実行される場合、ゲームは時代遅れのデータをロードする可能性があります。したがって、保存と読み込みデータに関連するスクリプトが実行順序で正しく順序付けられるようにすることが重要です。 5は、バイナリ形式または暗号化を使用して実現できます。バイナリフォーマットは、データを簡単に読み取りできないバイナリ形式に変換します。暗号化は、特定のキーでのみデコードできる方法でデータをエンコードすることにより、セキュリティの追加レイヤーを追加します。 🎜> PlayerPrefsは、Unity 5に保存とロード機能を実装するためのシンプルで便利な方法ですが、いくつかの制限があります。まず、整数、フロート、弦のみをサポートします。第二に、安全ではなく、簡単に操作できます。最後に、PlayerPrefsにはサイズ制限があり、これは大量のデータを備えたゲームの問題になる可能性があります。 Unity 5の複雑なデータ構造は、JSONシリアル化またはバイナリ形式を使用して実現できます。 JSONシリアル化を使用すると、複雑なデータ構造を簡単に保存およびロードできる文字列形式に変換できます。バイナリフォーマットは、データをバイナリ形式に変換するより安全な方法です。はい、Unity 5の異なるプラットフォームでデータを保存およびロードできます。ただし、データの保存とロードに選択する方法は影響する可能性があります。クロスプラットフォームの互換性。たとえば、PlayerPrefsはクロスプラットフォームに互換性がありますが、バイナリ形式はすべてのプラットフォームで互換性がない場合があります。 Unity 5の機能を保存およびロードすると、スクリプトの実行順序を確認し、データが正しくシリアル化またはフォーマットされていることを確認することで実行できます。そして、あなたがそれをリリースしようとするプラットフォームでゲームをテストします。 5保存とロードの量を最小化し、効率的なデータ構造を使用してロードし、スクリプトが十分に最適化されていることを確認することで実現できます。 UNITY 5?

Unity 5でAutoSave機能の実装5は、定期的な間隔または特定のイベントでゲームを自動的に保存するスクリプトを作成することで実行できます。このスクリプトは、マニュアル保存システムと同じようにデータを保存するために同じ方法を使用する必要があります。

以上がUnity 5の保存とロード機能のマスタリング5の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート