前回の記事で、おそらくリソースの読み込みについて触れ始めました。シーン リソースは特別なリソースです。ビルド設定に追加するだけで、API を通じて直接読み込むことができます。
しかし、他の種類のリソースについてはどうでしょうか? 例えばオンラインゲームを作ってバックグラウンドからデータを返してもらってキャラクターに銃を設置する場合、全ての銃をメンバーデータとして割り当てることは不可能なので、必ずどれを使用するかを読み込みたいので、現時点では、同様の名前またはパスによるリソースのロードをサポートする必要があります。
したがって、この章では、Unity にどのようなリソースがあるのか、それらをロードする方法、およびいくつかのロード方法が適用できるシナリオについて説明します。
参照によるロード
これまでの章では、特定のリソースを使用したい場合、コードにメンバー変数を追加し、Unity のシリアル化機能を利用してエディター パネルに表示し、シーンまたはプロジェクトにオブジェクトをドラッグ アンド ドロップします。ウィンドウ。リソースは対応する変数に割り当てられます。リソースをロードするこのメソッドは参照によってロードされます。
以前に実際のシーン ファイルを分析しました。ゲームオブジェクトであってもコンポーネント クラスであっても、シリアル化中に一意の ID が生成されます。この ID は参照関係を保存するために使用され、シーンの開始時に作成されます。既存のゲームオブジェクトをロードします。シーンを作成し、ファイル内の ID データに従ってすべての参照関係にインデックスを付けます。
しかし問題があり、実際に以前シーン内のオブジェクトのコンポーネント変数にPrefabを使って代入したのですが、その参照関係はどうなっているのでしょうか?
Demo.unity ファイルをテキスト モードで開き、箇条書きを割り当てた FireController オブジェクトの FireController コンポーネントを見つけてもよいでしょう。
ここでも fileID が表示されていることがわかりますが、シーン ファイル内でこの fileID の 2 番目の使用を検索することはできません。結局のところ、ここで割り当てられたプレハブはシーンではなくプロジェクト ウィンドウに存在するので、そこに注意を払います。グローバル検索が得意な友人は、Assets ディレクトリ全体を検索しようとすると、すぐにこの GUID が Bullet.prefab.meta ファイルに存在することがわかるでしょう。
開いて内容を確認すると、次のようになります。
このメタ ファイルに記録されている GUID が、シーン内のプレハブを参照する変数に格納されている GUID と一致していることがわかります。また、Bullet.prefab を再度開くと、fileID に対応するプレハブ上のコンポーネントを見つけることができます。
このとき実際に理解しているのは、シーン以外で直接参照できるリソースについては、シーン外のリソースファイルにはそのリソースのguidを格納した.metaファイルがあり、シーン外のリソースを参照する方法はこのガイドで検索してください。
Assets フォルダー内のすべてのファイルには .meta ファイルが含まれていることがよくわかります。これは、フォルダーを含むすべてのファイルが Unity で参照できることを意味します。
これは、ゲーム プロジェクトを git や svn、p4 などのバージョン管理システムにアップロードする必要がある場合、.meta ファイルをアップロードする必要があることも説明しています。アップロードされていない場合、他の人がプロジェクトを開いたときに、Unity新しい .meta ファイルが自動的に生成されます。その時点で、guid によって参照されるすべてのリソースは無効になります。
もちろん、.meta ファイルには GUID 情報だけでなく、他の多くの情報も保存されます。詳細については、各リソース タイプの高度なチュートリアルで後ほど説明します。
Unity がシーン内外のリソースの参照をどのように処理するかを理解すると、なぜパッケージ化できるのかを実際に理解できるようになります。Unity パッケージは、ビルド設定で追加されたシーンからすべてのリソース参照を検索し、使用されるすべてのリソースがパッケージ化されるからです。最終的なゲームパッケージ。
リソースフォルダー
コード メンバー内でコンポーネントやゲームオブジェクト、プレハブ リソースを直接参照していない場合、プレハブやその他のリソースを動的にロードするにはどうすればよいでしょうか? Unity には、Resources という名前のフォルダーという特別な暗黙のルールが用意されています。Assets ディレクトリでは、Resources という名前のフォルダーであれば問題なく、異なるディレクトリに複数の Resources フォルダーが同時に存在することができます。これらのファイルは、Unity によって均一に認識されます。その後、Resources.Load API を使用して内部のリソースをロードできます。
Unity - スクリプト API: Resources.Load docs.unity3d.com/ScriptReference/Resources.Load.html
新しいシーンをロードするのと少し似ています。相対パスを使用して Resources フォルダーの内容をロードできます。パスでは、パス区切り文字として \ の代わりに / を使用する必要があることに注意してください。
例えば:
- Assets/Test1/Resources/a.prefab の場合、ロード時にファイル拡張子なしで を使用します。
- Assets/Test1/Resources/BB/a.prefab の場合、ロード時に BB/a を使用します
- Assets/Test2/Resources/BB/a.prefab の場合、2 と競合し、Resources フォルダー内のすべてのファイルが同じ相対パスを持つことはできないと Unity から通知されます。
OK、試してみましょう。以前は、Bullet はメンバー変数に直接割り当てられていました。今では、Prefab リソースを Resources フォルダーに置きます。現在はリソース フォルダーがないので、新しい Resources フォルダーを作成します。 [プロジェクト] ウィンドウで [作成] > [フォルダー] をクリックし、Bullet プレハブ ファイルをそのフォルダーに直接ドラッグします (これはカットと同じです)。
Windows エクスプローラーでこの操作を直接実行している場合は、対応する .meta ファイルもカットする必要があることに注意してください。また、この .meta ファイルにはこのリソースの guid 情報が含まれているとも言いました。カットしない場合 カットされている場合離れてしまうと、元の参照関係は見つかりません (リソースとともに直接ロードされますが、影響しない可能性があります)。.meta ファイルは、リソースを切り取るときに自動的に処理されるため、Unity のプロジェクト ウィンドウには表示されません。
次に、前に弾丸を作成した FireController のコードを変更する必要があります。
using UnityEngine;
using Object = UnityEngine.Object;
public class FireController : MonoBehaviour
{
private bool isMouseDown = false;
private float lastFireTime = 0f;
private Vector3 fireDirection;
private AddVelocity bullet;
public string bulletResourcesPath;
public float fireInterval = 0.1f;
public Transform fireBeginPosition;
private void Start()
{
bullet = Resources.Load<AddVelocity>(bulletResourcesPath);
}
void Update()
{
if (Input.GetButton("Fire1"))
{
if (!isMouseDown)
{
isMouseDown = true;
lastFireTime = Time.time;
Fire();
}
else if (Time.time - lastFireTime > fireInterval)
{
lastFireTime = Time.time;
Fire();
}
}
else
{
isMouseDown = false;
}
}
void Fire()
{
// 在这里实现每次触发的逻辑
// 创建新的子弹,每次都是从模板bullet复制一个出来
AddVelocity newBullet = Object.Instantiate(bullet);
newBullet.transform.position = fireBeginPosition.position;
newBullet.SetDirection(fireDirection);
}
public void SetDirection(Vector3 direction)
{
fireDirection = direction;
}
}
私たちの変更は主に、以前のパブリック メンバーの箇条書きをプライベート メンバーに置き換えることです。このメンバーをシリアル化する必要はなくなりました。代わりに、文字列メンバーを使用して、エディターがリソース パスを入力できるようにします。
次に、Start メソッドの Resources.Load を通じてこのリソースを 1 回ロードします。その後の処理は前のメソッドと同じです。Resources.Load メソッドはジェネリック型、または C++ 用語でテンプレート型を持ちます。<> で満たされた型は、GetComponent と同様のメソッドを使用して、ロードされたゲームオブジェクトから取得されます。当然、ゲームオブジェクトをロードする必要があります。 <> には GameObject の種類を入力できます。
OK、エディターで箇条書きのリソース パス Bullet を直接入力しましょう。
もう一度実行すると、箇条書きも作成でき、以前と同じ効果が得られることがわかります。
この読み込み方法には欠点があり、Resources フォルダーに置かれたリソースは参照されているかどうかは関係なく、ゲームをパッケージ化するときにパッケージ化されてしまうため、Unity ではどれを使用するかわからないため、この方法を使用します。は、小規模なボリュームのリソースに適しています。
資産データベース
エディターモードでの専用リソースロードメソッドは、主にエディター内での拡張や機能操作に使用され、通常のゲーム動作ロジックとは独立していますが、エディターのゲームランタイムの概念に関わるため、本章では説明を省略します。エディター拡張機能の開発を具体的に説明するときまで保存しておきます。
アセットバンドル
Unity が提供するオーソドックスなゲームは、ゲームをパッケージ化してリリースした後に通常のリソースをロードする方式ですが、理解するのが非常に面倒な概念が多く、この章の一連の記事はまだ初期段階にあるため、これについては説明しません。ゲームのパッケージングについては後ほど詳しく説明することにし、リソース管理についてもう一度話しましょう。
考える質問
- Resources.Load はリソースを同期的に読み込み、コードの実行をブロックします。当然、公式 API には非同期バージョンがあります。非同期に変更した場合はどのように記述すればよいでしょうか?
次の章
上記では、参照による自動読み込みとパスによる動的読み込みの 2 つのリソース読み込み方法について説明しました。Resources.Load はイライラさせられますが、この段階ではまず Unity のリソース読み込みを学習するだけで十分です。
次の章では、エディター拡張機能について簡単に紹介します。Unity エディターは変更されていませんが、コードを通じて必要に応じて調整できます。これは、最新の商用ゲーム エンジンによって提供されるエディター拡張機能でもあります。拡張機能を通じて、私たちは、カスタマイズされたニーズにエンジンをより適切に対応させることができます。もちろん、エディタのロジックとゲームのロジックの違いも学びます。