- 投稿日:2020-05-22T17:04:00+09:00
【Unity】Endless Runnerについて
はじめに
UnityでRunゲームを作成しようと思った際に、何か参考にできる情報が無いかを探していたら、
Endless Runner - Sample Game
が見つかりました!Unityが作成したサンプルゲームです。
2020/05/16現在、AssetStoreからダウンロードする事が可能です!
アセットのページUnityサービスについて
広告、分析、IAPを簡単に実装する事ができるサービスです。
サービスダッシュボードでいくつかの詳細を構成し、少量のコードを記述するだけです。IAPの統合に使用されるコード
IAPHandler.cs
にIAPを統合するためのコードが記載されています。広告の処理に使用されるコード
広告に関するコードは
AdsForMission.cs
およびUnityAdsinitializer.cs
に記載されています。分析コードについては
いくつかの良い例が
GameManager.cs
にありますゲームマネージャー
GameManager.cs
はゲームの全体的なフローを制御するクラスです。GameManagerは、シングルトンと呼ばれるデザインパターンを使用します。シングルトンパターンは、ゲーム内に特定のクラスのインスタンスが1つしかないことを保証する方法です。これは、クラスにGameManagerなどの重要な責任がある場合に役立ちます。また、パブリック静的参照を使用して、他のクラスがこのインスタンスに簡単にアクセスできるようになります。
GameManagerも有限状態マシンの例です。有限ステートマシンは、ゲームが常に1つの状態のみになることを保証し、この状態が変化したときに何が起こるかを管理します。Trash Dashの状態には、スタートメニューの表示、ゲームのプレイ、ゲームオーバースクリーンの表示の3つがあります。有限状態機械は、ゲームの全体的な流れから個々のキャラクターの振る舞いまで、ゲームでの動作を管理する一般的な方法です。
シングルトンおよび有限状態マシンのコードを確認するには、GameManager.cs
を調べてコメントを読んでください。3つの状態を開始、実行、終了するためのコードは、LoadoutState.cs
、GameState.cs
、GameOverState.cs
の各ファイルにあります。シングルトンについて
オブジェクトプーリング
Trust Dashでは、1回のプレイセッションで数百のコインが発生することがあります。実行時に非常に多くのオブジェクトをインスタンス化して破棄すると、パフォーマンスに負担がかかる可能性があります。比較的コストのかかるコードが含まれ、頻繁で時間のかかる[ガベージコレクション](https://geechs-magazine.com/tag/tech/20160229)につながる可能性があります。
このオーバーヘッドを削減するために、Trash Dashはオブジェクトプーリングと呼ばれる手法を使用します。オブジェクトプーリングは、オブジェクトを作成して破棄するのではなく、オブジェクトを一時的に非アクティブ化し、必要に応じてリサイクルする手法です。
ゲームが始まると、いくつかの非アクティブなコインGameObjectが生成され、「プール」に配置されます。新しいコインが必要になると、プールから1つが要求され、有効になります。コインが収集されるか画面を離れると、コインは無効になり、プールに戻されます。
Trash Dashのオブジェクトプーリングコードを確認するには、
TrackManager.cs
、Coin.cs
、およびPooler.cs
をご覧ください。
Unityでのオブジェクトプーリングの一般的なガイドについては、Unity Learnサイトのこのチュートリアルを参照してください。テクニック
アーキテクチャの決定は、通常、ゲームの多くのクラスまたは部分に影響を与えますが、テクニックの焦点は小さくなります。テクニックは単一の関数またはファイルにのみ影響する可能性がありますが、それでも問題の解決に役立ちます。
Trash Dashで使用されているいくつかのテクニックを見て、それらが解決する問題を見てみましょう。原点リセット
宇宙探査ゲームやゴミ箱ダッシュなどの「無限」ゲームなど、プレイヤーが遠くまで移動するゲームでは、開発者はプレイヤーの位置の処理方法を決定する必要があります。プレーヤーのGameObjectを移動するだけの場合、プレーヤーの
transform.position
の値は時間の経過とともに次第に高くなります。これは、浮動小数点不正確性と呼ばれるものによる問題を引き起こす可能性があります。浮動小数点の不正確さは、浮動小数点数の値が大きいほど、精度が低くなることを意味します。これはコンピューターが数値データを保存する方法の制限であり、Unityに固有のものではありません。プレイ可能な領域が大きい、または無限のゲームでは、位置を格納するために使用される浮動小数点数が問題を引き起こすほど大きくなる可能性があります。
GameObjectの位置に不正確な値があると、動き回ったり、ちらついたり、飛び出したりするように見えることがあります。この問題を解決する方法はいくつかありますが、どれが最適かはゲームによって異なります。Trash Dashでは、origin resetと呼ばれる手法を使用してこの問題を解決しています。つまり、プレーヤーがワールドの原点(つまり、ワールドの位置0、0、0)を超えて特定の距離を移動すると、シーンのすべてが原点に向かって移動します。これにより、位置に使用される値が常に低くなり、不正確になりにくくなります。原点リセットはシームレスに行われ、プレイヤーはそれを認識しません。
原点リセット手法に使用されるコードを確認するには、TrackManager.cs
を見てください。湾曲したワールドシェーダー
Trash Dashでは、プレーヤーの前にトラックセクションをスポーンし、プレーヤーの後ろにあるトラックセクションを削除して、無限のトラックを作成します。プレイヤーがずっと先を見ることができる場合、事前に多くのトラックセクションをスポーンする必要があります。これにより、パフォーマンスの問題が発生する可能性があります。
これに加えて、世界はコイン、障害物、キャラクターでいっぱいです。繰り返しになりますが、プレイヤーがそれらの前に長い距離を見ることができる場合、Unityは、これらのオブジェクトがすべて、対話するのに十分近くなる前に画面に描画する必要があります。これは、特にモバイルで、パフォーマンスの問題を引き起こす可能性もあります。
この問題を解決するために、世界は地平線でプレイヤーから離れて曲がります。これは無限の世界の錯覚を作成し、トラックピースのスポーンを非表示にし、プレイヤーがそれらに近づくまで、コインや障害物をスポーンする必要がないことを意味します。
シーンを調べると、世界の実際のジオメトリは湾曲しておらず、平坦であることがわかります。カーブしたエフェクトは、シェーダーによって作成されます。シェーダーは、オブジェクトを画面に描画する方法をUnityに指示するコードです。この場合、シェーダーはレベルが湾曲した場合の外観を計算し、その計算に基づいてスクリーンにピクセルを描画する場所をUnityに通知します。
これがどのように機能するかを確認するために調べるファイルは、
WorldCurver.cs
とCurvedCode.cginc
です。
シェーダーコードのガイド参考文献
Trash Dashには、アプローチとテクニックのさらに興味深い例がいくつかあります。魚の回転に使用されるシェーダー、AssetBundlesを使用してキャラクターとテーマをロードする方法、およびプレーヤーデータが保存される方法を見てみましょう。
パフォーマンスの最適化の詳細については、UnityのLearnサイトでこれらの記事を読んでください。
Unityを使用してモバイルゲームを作成する方法の詳細については、Unity Learnサイトのこのセクションをご覧ください。
- 投稿日:2020-05-22T13:12:58+09:00
[Unity] シリアライズを保持したまま変数名を置き換える
基本的には自分用メモなので結論から言うと
スクリプトの先頭でusing UnityEngine.Serialization;を宣言し、
[FormerlySerializedAs("previousName")] var newtName;で変数をpreviousName->newtNameに置き換えます。
Unityで変数名を置き換える場合、単変数ならGrepして置き換えて再度Inspectorから適当に値を設定、でいいのですが、例えば
[SerializeField] Tile[] m_treasureBaseTileArr = null;のような配列で、既に何十ものオブジェクトが入れてあるような場合だとメンドクセ、、となることがあります。
(この例だとパーツがきれいにid順に並んでいるのでまとめてドラッグ&ドロップしてもOKなのですが・・・。)
例えば上記の例で、中身を保持したまま
m_treasureBaseTileArr をm_treasureTileArr
に変更したい場合は、スクリプトの先頭でusing UnityEngine.Serialization;を宣言し、
[FormerlySerializedAs("m_treasureBaseTileArr")] [SerializeField] Tile[] m_treasureTileArr = null;のように
[FormerlySerializedAs("m_treasureBaseTileArr")]
を変数の直前についかしてから
m_treasureBaseTileArr をm_treasureTileArr
に全置換します (FormerlySerializedAs()の中も置換しちゃわないよう注意)こうすることでシリアライズされた値を保持したまま変数を変更することができます。
- 投稿日:2020-05-22T13:12:58+09:00
[Unity] 中身を保持したまま変数名を置き換える
基本的には自分用メモなので結論から言うと
スクリプトの先頭でusing UnityEngine.Serialization;を宣言し、
[FormerlySerializedAs("previousName")] var newtName;で変数をpreviousName->newtNameに置き換えます。
Unityで変数名を置き換える場合、単変数ならGrepして置き換えて再度Inspectorから適当に値を設定、でいいのですが、例えば
[SerializeField] Tile[] m_treasureBaseTileArr = null;のような配列で、既に何十ものオブジェクトが入れてあるような場合だとメンドクセ、、となることがあります。
(この例だとパーツがきれいにid順に並んでいるのでまとめてドラッグ&ドロップしてもOKなのですが・・・。)
例えば上記の例で、中身を保持したまま
m_treasureBaseTileArr をm_treasureTileArr
に変更したい場合は、スクリプトの先頭でusing UnityEngine.Serialization;を宣言し、
[FormerlySerializedAs("m_treasureBaseTileArr")] [SerializeField] Tile[] m_treasureTileArr = null;のように
[FormerlySerializedAs("m_treasureBaseTileArr")]
を変数の直前についかしてから
m_treasureBaseTileArr をm_treasureTileArr
に全置換します (FormerlySerializedAs()の中も置換しちゃわないよう注意)こうすることでシリアライズされた値を保持したまま変数を変更することができます。
- 投稿日:2020-05-22T03:12:51+09:00
C#でstaticが何か分からずに詰まってしまったので備忘録
初投稿です。Unity初心者の私がstaticが何者なのか分からなくなったので忘れないように記しておきます。
間違っていたら指摘していただけると嬉しいですStaticとは何ぞ?
Staticは静的と訳されています
クラスのメンバーを定義する時に下記のようにstaticを付けることで
static 型名 フィールド名
(例: static float Sin)
その変数は静的変数・静的メソッドになります静的って何だよ
静的とは、静的メンバー(クラスやオブジェクトの持つ変数や関数)の宣言に使用します。
静的メンバーは、特定のオブジェクトではなく、型自体に属するメンバーです。
少なくとも
・静的である=>動かなく値は固定=>(constのような)定数
という事ではないです。自分は脳内でこのように勝手に変換してしまってハマっていました。じゃあ何をやっているの?
staticはそのクラスが持つ変数やメソッドで有ることを示します。
動かせないお弁当箱を置いておくようなもので中身を見たり中身を入れ替えたり出来ます。いちいちインスタンスを取得してからアクセスしていましたが、
インスタンスを取得せずアクセスできるようになります。静的クラス
下記のようにstaticを付けることでstaticとして宣言され、staticメソッドのみが含まれます
public static class Math
public static class Math //静的クラス { public static readonly float PI = 3.14f; public static float CircumferenceLength(float diameter) { return diameter * PI; //直径から円周を返す雑メソッド } //static(静的クラスでは)が無いのでエラー //静的クラスでインスタンスのメンバーを宣言することはできません。と言われる public /*static*/ int Abs(float val) { return (int)Mathf.Abs(val); //絶対値にしてintで返すメソッド、なおエラーを吐く } }静的フィールドとメソッド
この例では、新しい従業員の名前と ID を読み取り、従業員数のカウンターを 1 つインクリメントして、新しい従業員の情報と従業員数を表示します。
NAKAMA_Manager.csusing UnityEngine; public class NAKAMA_Manager : MonoBehaviour { public void Start() { var employee1 = new Employee("一般人", 5); Employee.AddEmployee(); Debug.Log($"NAME: {employee1.name}"); Debug.Log($"HP: {employee1.hp}"); Debug.Log($"Employee数: {Employee.employeeCounter}"); //Employeeクラスにアクセス var employee2 = new Employee("パチュリー", 30000); Employee.AddEmployee(); Debug.Log($"NAME: {employee2.name}"); Debug.Log($"HP: {employee2.hp}"); Debug.Log($"Employee数: {Employee.employeeCounter}"); } } public class Employee //従業員 { public string name; //インスタンスされる度(newされる度)に生成される変数) public int hp; //インスタンスされる度(newされる度)に生成される変数) public Employee(string name, int hp) { this.name = name; this.hp = hp; } public static int employeeCounter; //クラスが持つ変数 public static int AddEmployee() { employeeCounter++; return employeeCounter; } }まとめ
・クラスのメンバーを定義する時にstaticを付けると静的宣言、静的メソッドになる
・静的メンバーは、特定のオブジェクトではなく、型自体に属する
・インスタンスを取得せずともアクセスできるようになる参考にしたサイト
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/static
- 投稿日:2020-05-22T03:12:51+09:00
Unityでstaticが何か分からずに詰まってしまったので備忘録
初投稿です。Unity初心者の私がstaticが何者なのか分からなくなったので忘れないように記しておきます。
間違っていたら指摘していただけると嬉しいですStaticとは何ぞ?
Staticは静的と訳されています
クラスのメンバーを定義する時に下記のようにstaticを付けることで
static 型名 フィールド名
(例: static float Sin)
その変数は静的変数・静的メソッドになります静的って何だよ
静的とは、静的メンバー(クラスやオブジェクトの持つ変数や関数)の宣言に使用します。
静的メンバーは、特定のオブジェクトではなく、型自体に属するメンバーです。
少なくとも
・静的である=>動かなく値は固定=>(constのような)定数
という事ではないです。自分は脳内でこのように勝手に変換してしまってハマっていました。じゃあ何をやっているの?
staticはそのクラスが持つ変数やメソッドで有ることを示します。
動かせないお弁当箱を置いておくようなもので中身を見たり中身を入れ替えたり出来ます。Unityではいちいちインスタンスを取得してからアクセスしていましたが、
インスタンスを取得せずアクセスできるようになります。静的クラス
下記のようにstaticを付けることでstaticとして宣言され、staticメソッドのみが含まれます
public static class Math
public static class Math //静的クラス { public static readonly float PI = 3.14f; public static float CircumferenceLength(float diameter) { return diameter * PI; //直径から円周を返す雑メソッド } //static(静的クラスでは)が無いのでエラー //静的クラスでインスタンスのメンバーを宣言することはできません。と言われる public /*static*/ int Abs(float val) { return (int)Mathf.Abs(val); //絶対値にしてintで返すメソッド、なおエラーを吐く } }静的フィールドとメソッド
この例では、新しい従業員の名前と ID を読み取り、従業員数のカウンターを 1 つインクリメントして、新しい従業員の情報と従業員数を表示します。
NAKAMA_Manager.csusing UnityEngine; public class NAKAMA_Manager : MonoBehaviour { public void Start() { var employee1 = new Employee("一般人", 5); Employee.AddEmployee(); Debug.Log($"NAME: {employee1.name}"); Debug.Log($"HP: {employee1.hp}"); Debug.Log($"Employee数: {Employee.employeeCounter}"); //Employeeクラスにアクセス var employee2 = new Employee("パチュリー", 30000); Employee.AddEmployee(); Debug.Log($"NAME: {employee2.name}"); Debug.Log($"HP: {employee2.hp}"); Debug.Log($"Employee数: {Employee.employeeCounter}"); } } public class Employee //従業員 { public string name; //インスタンスされる度(newされる度)に生成される変数) public int hp; //インスタンスされる度(newされる度)に生成される変数) public Employee(string name, int hp) { this.name = name; this.hp = hp; } public static int employeeCounter; //クラスが持つ変数 public static int AddEmployee() { employeeCounter++; return employeeCounter; } }まとめ
・クラスのメンバーを定義する時にstaticを付けると静的宣言、静的メソッドになる
・静的メンバーは、特定のオブジェクトではなく、型自体に属する
・Unityではインスタンスを取得せずともアクセスできるようになる参考にしたサイト
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/static