この記事のレビューを査読してくれたVincent Quarlesに感謝します。 このチュートリアルでは、ゲームの保存とロード機能の実装を終了します。プレイヤーゲームデータの拡張に関する以前のチュートリアルでは、統計や在庫などのプレーヤー関連データを保存およびロードしたことに成功しましたが、今では最も困難な部分である世界オブジェクトに取り組みます。最終的なシステムは、長老のスクロールゲームを連想させる必要があります。すべてのオブジェクトは、無期限に保存されています。
練習するためにプロジェクトが必要な場合は、最後のチュートリアルで完了したプロジェクトのバージョンを次に示します。 1つのポーションと1つの剣のアイテムを生成するゲーム内の相互作用可能なオブジェクトでアップグレードされました。それらを生み出すことができ、((
> spawned)を拾うことができ、状態を正しく保存してロードする必要があります。プロジェクトの完成バージョン(Save Systemを完全に実装した)は、この記事の下部にあります。
プロジェクトの開始ファイルをダウンロード
プロジェクトzipダウンロード
キーテイクアウト
デリゲートイベントシステムを利用して、オブジェクトに状態を保存する時期に通知し、保存/負荷システムのモジュール性と柔軟性を高めます。
レベルマスターオブジェクトを実装して、オブジェクトの産卵とdepawningを管理し、世界のオブジェクトがゲームセッション全体で状態を維持することを保証します。- シリアル化可能なクラスを使用して、さまざまな種類のオブジェクトに対して簡単に拡張または変更できる位置などのオブジェクトプロパティを保存します。
- オブジェクトスクリプト内のイベントを保存するための適切なサブスクリプションとunsubscriptionを確認して、エラーを回避し、ゲーム状態を効果的に管理します。 複雑なデータ構造を処理し、データの整合性を確保するために、バイナリフォーマットを使用して保存およびロードするための堅牢なシステムを開発します。
- システムをテストおよび拡張して、新しいオブジェクトの種類と機能を含め、さまざまなゲーム開発ニーズに合わせてシステムの適応性とスケーラビリティを実証します。
- 実装理論
- オブジェクトを実装する前に、オブジェクトを保存およびロードするシステムを分解する必要があります。何よりもまず、オブジェクトを生成してデスポーンする何らかのレベルマスター オブジェクトが必要です。レベルに保存されたオブジェクトをスポーンする必要があります(レベルをロードして新たに起動していない場合)、デパーンオブジェクトを拾い上げ、オブジェクトに自分自身を保存する必要があることを通知し、オブジェクトのリストを管理する必要があります。たくさん聞こえますが、それをフローチャートに入れましょう:
-
基本的に、ロジック全体がオブジェクトのリストをハードドライブに保存しています。これは、次にレベルがロードされると、移動し、プレイを開始するとすべてのオブジェクトが生成されます。簡単に聞こえますが、悪魔は詳細にあります:どのオブジェクトを保存するオブジェクトをどのようにして、どのようにしてそれらを引き戻すことができますか?
代表者とイベント公式の代表団のドキュメントと公式イベントのドキュメントを読むことができます。しかし、心配しないでください:公式文書のテクノバブルの多くを理解していないので、私はそれを平易な英語に入れます:
Delegate
代表者を関数の青写真と考えることができます。関数がどのように見えるかを説明しています:その返品タイプとは何か、そしてそれが受け入れる議論。たとえば、
public delegate void SaveDelegate(object sender, EventArgs args);
では、これはイベントとどのように結びついていますか?
イベント
イベントは、関数の
ボックスと考えることができます。デリゲート(青写真)に一致する関数のみを受け入れ、実行時に機能を配置および削除できます。
その後、いつでもイベントをトリガーできます。つまり、現在ボックスにあるすべての機能を一度に実行することを意味します。次のイベント宣言を検討してください
この構文は次のように述べています:パブリックイベントを宣言します(誰でも購読できます - 後で説明します)。
イベントへの購読は、基本的に「ボックスに関数を置く」ことを意味します。構文は非常に簡単です。私たちのイベントがよく知られているGlobalObjectクラスで宣言されており、イベントに登録する必要がある
potiondroppablepublic event SaveDelegate SaveEvent;という名前のポーションオブジェクトクラスがあるとしましょう。
ここで構文を説明しましょう。最初に、説明された委任標準に適合する関数が必要です。オブジェクトのスクリプトには、SaveFunctionという名前のこのような関数があります。後で自分で書きますが、今のところ、オブジェクトをハードドライブに保存するための機能機能であると仮定して、後でロードできます。
それがあるとき、私たちは単にその関数を開始時にボックスに入れたり、スクリプトを覚醒させたり、破壊したときに削除したりします。 (登録解除は非常に重要です:破壊されたオブジェクトの関数を呼び出すと、実行時にNULL参照例外が得られます)。宣言されたイベントオブジェクトにアクセスし、追加演算子を使用して機能名を使用してこれを行います。
注:ブラケットや引数を使用して関数を呼び出していません。関数の名前を使用しているだけです。他に何も使用していません
それでは、ゲームのフローの例で最終的にこれが何をするか説明しましょう。ロジックフロー
ゲームの流れを通して、プレイヤーの行動が世界に2つの剣と2つのポーションを生み出したと仮定しましょう(たとえば、プレーヤーは戦利品で胸を開けました)。
これらの4つのオブジェクトは、セーブイベントで機能を登録します。
次に、プレイヤーが世界から1つの剣と1つのポーションを拾うと仮定しましょう。オブジェクトが「ピックアップ」されると、彼らはプレーヤーの在庫の変化を効果的にトリガーし、それから自分自身を破壊します(魔法を台無しにします、私は知っています):
そして、プレイヤーがゲームを保存することにしたとしましょう。たぶん、彼らは本当に3回鳴ったその電話に答える必要があるかもしれません(ねえ、あなたは素晴らしいゲームを作りました):
基本的に、ボックス内の関数が1つずつトリガーされ、すべての機能が完了するまでゲームはどこにも行かないということです。 「自らを保存する」すべてのオブジェクトは、基本的にリストに自体を書き留めています。次のゲームロードでは、レベルマスターオブジェクトによって検査され、リストにあるすべてのオブジェクトがインスタンス化されます(スポーン)。それだけです。これまでのところ、これまでの記事に従っていたら、基本的にすぐに実装を開始する準備ができています。それにもかかわらず、私たちはここでいくつかの具体的なコードの例に行きます、そしていつものように、あなたが記事の最後にあなたを待っている完成したプロジェクトがあなたが全体がどのように見えるかを見たいならあなたを待っています。
code
最初に既存のプロジェクトを進めて、すでに中にあるものに慣れてみましょう。
ご覧のとおり、既に述べた2つのオブジェクトのスポーナーとして機能するこれらの美しく設計されたボックスがあります。 2つのシーンのそれぞれにペアがあります。すぐに問題を見ることができます。シーンを移行したり、
f5/f9を使用して保存/負荷をかけたりすると、産卵したオブジェクトが消えます。
ポーションオブジェクトのリストを作成します
- 剣のオブジェクトのリストを作成します
- グローバルセーブイベントを実装してください
- 保存関数を使用してイベントを購読します
- レベルマスターオブジェクトを実装
- ゲームをロードしている場合、レベルマスターをすべて保存したオブジェクトをすべてスポーンします。
- あなたが見ることができるように、これはそのような基本的な機能がそうなることを望むほど些細なことではありません。実際、そこに既存のゲームエンジン(CryEngine、UDK、Unreal Engine 4、その他)は、実際に簡単な保存/負荷機能の実装を準備していません。これは、ご想像のとおり、メカニックを保存することは各ゲームに本当に固有であるためです。通常、保存する必要があるクラスをオブジェクトにするだけです。完成/アクティブなクエスト、派factの親しみやすさ/敵意、一部のゲームの現在の気象条件など、世界の状態です。それは非常に複雑になりますが、保存メカニックの適切な基盤により、より多くの機能を使用して簡単にアップグレードすることができます。 オブジェクトクラスリスト
- 最初に簡単なもの、つまりオブジェクトリストを始めましょう。プレーヤーのデータは、Serializablesクラスのデータを簡単に表現して保存およびロードされます。
コードをうまく構成するために、シリアル化可能性の最後にある簡単なクラスから始めます。
なぜ私たちが基本クラスを使用しているのではないのか疑問に思うかもしれません。答えは、私たちができるということですが、節約が必要な特定のアイテムプロパティを追加または変更する必要があることを実際に知ることはありません。さらに、これはコードの読みやすさの方がはるかに簡単です
今では、私がdroppable
今、プレイヤーのデータとは異なり、実際にはいつでもプレーヤーが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つの追加ファイルです。
初期テスト
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);
さて、それらを生成する必要があります。レベルマスターでは、ポーションを生成するループのために私たちのために:
public event SaveDelegate SaveEvent;serializablesクラス
を追加します
イベントを保存するためにサブスクライブするアイテムのスクリプトを作成します- レベルマスターにインスタンスロジックを追加します。
- 結論
- 今のところ、システムは非常に粗雑です。ハードドライブに複数の保存ファイルがあり、オブジェクトの回転は保存されません(剣、プレイヤーなど)、シーンの移行中にプレーヤーを配置するためのロジック(ただし、そうではありません(読み込み)は少し風変わりです。
これらはすべて、ソリッドシステムが整ったら解決するための小さな問題です。このチュートリアルと完成したプロジェクトをいじくり回して、システムを改善できるかどうかを確認することをお勧めします。
でも、ゲームでセーブ/ロードメカニックを行うための非常に信頼性の高い堅実な方法ですが、これらの
例とはとは異なる場合があります。
約束されているように、参照のために必要な場合、またはどこかに立ち往生したために、完成したプロジェクトが完成しました。保存システムは、このチュートリアルの指示と同じ命名スキームで実装されます。
実行順序は、Unity 5の保存および負荷機能にどのように影響しますか?どのスクリプトが実行されますか。これは、保存およびロード機能に大きな影響を与える可能性があります。たとえば、データをロードするスクリプトがデータを保存するスクリプトの前に実行される場合、ゲームは時代遅れのデータをロードする可能性があります。したがって、保存と読み込みデータに関連するスクリプトが実行順序で正しく順序付けられるようにすることが重要です。 5は、バイナリ形式または暗号化を使用して実現できます。バイナリフォーマットは、データを簡単に読み取りできないバイナリ形式に変換します。暗号化は、特定のキーでのみデコードできる方法でデータをエンコードすることにより、セキュリティの追加レイヤーを追加します。 🎜> PlayerPrefsは、Unity 5に保存とロード機能を実装するためのシンプルで便利な方法ですが、いくつかの制限があります。まず、整数、フロート、弦のみをサポートします。第二に、安全ではなく、簡単に操作できます。最後に、PlayerPrefsにはサイズ制限があり、これは大量のデータを備えたゲームの問題になる可能性があります。 Unity 5の複雑なデータ構造は、JSONシリアル化またはバイナリ形式を使用して実現できます。 JSONシリアル化を使用すると、複雑なデータ構造を簡単に保存およびロードできる文字列形式に変換できます。バイナリフォーマットは、データをバイナリ形式に変換するより安全な方法です。完成したプロジェクトをダウンロード:
Project Githubページ
プロジェクトzipダウンロード
Unityの保存とロード機能の習得に関するよくある質問(FAQ)
Unity 5に保存システムを実装する最良の方法は何ですか?
Unity 5に保存システムを実装する最良の方法は、PlayerPrefsクラスを使用することです。 PlayerPrefsは、ゲームセッション間でデータを保存および取得する簡単な方法です。これにより、整数、フロート、文字列の形でデータを保存およびロードできます。ただし、PlayerPrefsは安全ではなく、機密データに使用されるべきではないことに注意することが重要です。より複雑なデータまたは安全なデータについては、バイナリフォーマッターまたはJSONシリアナーの使用を検討することをお勧めします。 Unityでは、PlayerPrefs、JSON Serialization、またはバイナリフォーマットを使用して5を実現できます。 PlayerPrefsは最も簡単な方法であり、整数、フロート、文字列を保存およびロードできます。 JSONのシリアル化はもう少し複雑ですが、より柔軟性とセキュリティを可能にします。バイナリフォーマットは最も安全な方法ですが、最も複雑です。
以上がUnity 5の保存とロード機能のマスタリング5の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このチュートリアルは、AWSサービスを使用してサーバーレスイメージ処理パイプラインを構築することをガイドします。 APIゲートウェイ、Lambda関数、S3バケット、およびDynamoDBと対話するECS Fargateクラスターに展開されたnext.jsフロントエンドを作成します。 th

このパイロットプログラム、CNCF(クラウドネイティブコンピューティングファンデーション)、アンペアコンピューティング、Equinix Metal、およびActuatedのコラボレーションであるCNCF GithubプロジェクトのARM64 CI/CDが合理化されます。 このイニシアチブは、セキュリティの懸念とパフォーマンスリムに対処します

このGOベースのネットワーク脆弱性スキャナーは、潜在的なセキュリティの弱点を効率的に識別します。 Goの同時機能機能を速度で活用し、サービスの検出と脆弱性のマッチングが含まれます。その能力と倫理を探りましょう

ウェブサイトの構築は最初のステップに過ぎません:SEOとバックリンクの重要性 ウェブサイトを構築することは、それを貴重なマーケティング資産に変換するための最初のステップにすぎません。検索エンジンでのWebサイトの可視性を向上させ、潜在的な顧客を引き付けるために、SEO最適化を行う必要があります。バックリンクは、ウェブサイトのランキングを改善するための鍵であり、Googleや他の検索エンジンにWebサイトの権限と信頼性を示しています。 すべてのバックリンクが有益であるわけではありません:有害なリンクを特定して回避する すべてのバックリンクが有益であるわけではありません。有害なリンクはあなたのランキングに害を及ぼす可能性があります。優れた無料のバックリンクチェックツールは、ウェブサイトへのリンクのソースを監視し、有害なリンクを思い出させます。さらに、競合他社のリンク戦略を分析し、それらから学ぶこともできます。 無料のバックリンクチェックツール:SEOインテリジェンスオフィサー


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

Dreamweaver Mac版
ビジュアル Web 開発ツール

メモ帳++7.3.1
使いやすく無料のコードエディター

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。
