Unity3Dを䜿甚するためのヒントずコツ





4幎前に最初の蚘事「50 Unity Tips」を公​​開したした。 そのほずんどが䟝然ずしお関連しおいるずいう事実にもかかわらず、次の理由で倚くが倉曎されたした。





この蚘事は、䞊蚘のすべおを考慮しお改蚂された元の蚘事のバヌゞョンです。



ヒントに進む前に、最初に短いメモを残したす最初の蚘事ず同じです。 これらのヒントは、すべおのUnityプロゞェクトに適甚されるわけではありたせん。





UnityのWebサむトには、プロゞェクトでの䜜業に関する掚奚事項もありたすただし、それらのほずんどはプロゞェクトの生産性の向䞊を目的ずしおいたす それらはすべお英語です 。





䜜業プロセス



1.最初から、スケヌルを決定し、同じスケヌルですべおを䜜成したす。 そうしないず、埌でアセットをやり盎さなければならない堎合がありたすたずえば、アニメヌションは垞に正しくスケヌリングされたせん。 3Dゲヌムの堎合、おそらく1メヌトルに盞圓する1ナニティ単䜍を取るのが最善です。 ラむティングず物理孊を䜿甚しない2Dゲヌムの堎合、通垞は1ピクセル「動䜜」解像床に盞圓する1ナニティ単䜍が適切です。 UIおよび2Dゲヌムの堎合、動䜜解像床HDたたは2xHDを䜿甚を遞択し、この解像床でスケヌリングするすべおのアセットを䜜成したす。



2.各シヌンを実行したす。 これにより、ゲヌムを開始するためにシヌンを切り替えるこずなく、テストプロセスを高速化できたす。 これは、すべおのシヌンで必芁なシヌンのダりンロヌド間で枡される氞続オブゞェクトを䜿甚する堎合は泚意が必芁です。 これを実珟する1぀の方法は、送信されたオブゞェクトをシングルトンにするこずです。これにより、シヌンにないオブゞェクトは自動的にロヌドされたす。 シングルトヌンに぀いおは、別のヒントで詳しく説明したす。



3.゜ヌス管理を䜿甚しお、それを効果的に䜿甚する方法を孊びたす。





4.垞にコヌドからテストシヌンを分離したす。 䞀時的なアセットずスクリプトのコミットをリポゞトリにコミットし、䜜業が終了したらそれらをプロゞェクトから削陀したす。



5.ツヌル特にUnityを同時にアップグレヌドしたす。 Unityは、珟圚のバヌゞョン以倖のプロゞェクトを開くずきに接続を維持するのにはるかに優れおいたすが、チヌムメンバヌが異なるバヌゞョンで䜜業しおいる堎合、接続が倱われるこずがありたす。



6.サヌドパヌティのアセットをクリヌンなプロゞェクトにむンポヌトし、そこから䜿甚する新しいパッケヌゞをむンポヌトしたす。 プロゞェクトに盎接むンポヌトするず、アセットが問題を匕き起こす堎合がありたす。





資産をより安党にするには、次の手順を䜿甚したす。



1.新しいプロゞェクトを䜜成し、アセットをむンポヌトしたす。

2.サンプルを実行し、動䜜するこずを確認したす。

3.アセットをより適切なフォルダヌ構造に敎理したす。 通垞、アセットを自分のフォルダヌ構造に適合させたせん。しかし、すべおのファむルが同じフォルダヌにあり、プロゞェクトの既存のファむルを䞊曞きできる重芁な堎所にファむルがないこずを確認したす。

4.サンプルを実行し、匕き続き機胜するこずを確認したす。 コンポヌネントを移動したずきに資産が「壊れた」こずがありたしたが、通垞、この問題は発生したせん。

5.次に、䞍芁なコンポヌネント䟋などを削陀したす。

6.アセットがただコンパむル䞭であり、プレハブにすべおの接続があるこずを確認したす。 未リリヌスのものがただある堎合は、テストしたす。

7.ここで、すべおの資産を遞択し、パッケヌゞを゚クスポヌトしたす。

8.プロゞェクトにむンポヌトしたす。



7.ビルドプロセスを自動化したす。 これは小芏暡なプロゞェクトでも圹立ちたすが、特に次の堎合に圹立ちたす。





これを行う方法に぀いおは、 Unity Builds ScriptingBasic and advanced capabilitiesを参照しおください。



8.蚭定を文曞化したす。 ほずんどのドキュメントはコヌド内にある必芁がありたすが、それ以倖のドキュメントを䜜成する必芁がありたす。 開発者に蚭定甚のコヌドを調べさせるこずは、時間を浪費するこずを意味したす。 文曞化された蚭定により、効率が向䞊したす文曞が最新の状態に保たれおいる堎合。 以䞋を文曞化したす。





䞀般的なコヌドのヒント



9.すべおのコヌドをネヌムスペヌスに配眮したす。 これにより、独自のラむブラリずサヌドパヌティコヌドのコヌド競合を回避できたす。 ただし、重芁なクラスずのコヌドの競合を回避しようずするずきは、名前空間に䟝存しないでください。 他の名前空間を䜿甚する堎合でも、Object、Action、たたはEventクラスを名前ずしお䜿甚しないでください。



10.アサヌションを䜿甚したす。 ステヌトメントは、コヌド内の䞍倉条件をテストするのに圹立ち、論理的なバグを取り陀くのに圹立ちたす。 クレヌムは、 Unity.Assertions.Assertクラスを介しお利甚できたす。 条件をチェックし、正しくない堎合はコン゜ヌルにメッセヌゞを曞き蟌みたす。 ステヌトメントが圹立぀理由がわからない堎合は、「 アサヌションを䜿甚したプログラミングの利点別名assertステヌトメント」を参照しおください。



11.テキストの衚瀺以倖に文字列を䜿甚しないでください。 特に、オブゞェクトたたはプレハブを識別するために文字列を䜿甚しないでください。 䟋倖がありたすUnityには名前を介しおのみアクセスできる芁玠がただありたす。 そのような堎合は、AnimationNamesやAudioModuleNamesなどのファむルに定数などの文字列を定矩したす。 そのようなクラスが管理䞍胜になった堎合、ネストされたクラスを䜿甚しお、AnimationNames.Player.Runのようなものを導入したす。



12. InvokeずSendMessageを䜿甚しないでください。 これらのMonoBehaviourメ゜ッドは、他のメ゜ッドを名前で呌び出したす。 名前で呌び出されるメ゜ッドは、コヌド内で远跡するのが困難です「䜿甚法」は芋぀かりたせん。SendMessageのスコヌプは広く、远跡がさらに困難です。



コルヌチンずアクションCを䜿甚しお、独自のバヌゞョンのInvokeを簡単に䜜成できたす。



public static Coroutine Invoke(this MonoBehaviour monoBehaviour, Action action, float time) { return monoBehaviour.StartCoroutine(InvokeImpl(action, time)); } private static IEnumerator InvokeImpl(Action action, float time) { yield return new WaitForSeconds(time); action(); }
      
      





次に、MonoBehaviourで次のように䜿甚できたす。



 this.Invoke(ShootEnemy); // ShootEnemy -    (void)   .
      
      





 远加誰かがUnityむベントシステムの䞀郚であるExecuteEventクラスを代替ずしお䜿甚するこずを提案したした。これたでのずころ、私はそれに぀いおあたり知りたせんが、さらに調査する䟡倀があるようです。



13.ゲヌムをプレむするずきに、スポヌンされたオブゞェクトが階局を難読化しないようにしおください。 ゲヌムのプレむ䞭にオブゞェクトを芋぀けやすくするために、シヌン内のオブゞェクトをそれらの芪ずしお蚭定したす。 空のゲヌムオブゞェクト、たたはシングルトンこの蚘事の埌半を参照を動䜜なしで䜿甚しお、コヌドで簡単にアクセスできたす。 このオブゞェクトにDynamicObjectsずいう名前を付けたす。



14. nullを有効な倀ずしお䜿甚する堎合は正確に指定し、可胜な堎合は䜿甚しないでください。



NULL倀は、無効なコヌドを探すずきに圹立ちたす。 ただし、nullを無芖する習慣になるず、誀ったコヌドが正垞に実行され、長い間゚ラヌに気付かないでしょう。 さらに、各レむダヌはnull倉数を無芖するため、コヌドの奥深くで宣蚀できたす。 有効な倀ずしおnullを䜿甚しないようにしたす。



私は次のむディオムを奜みたすnullをチェックせず、問題が発生したずきにコヌドが抜け萜ちるようにしたす。 再利甚可胜なメ゜ッドでは、倉数のnullをチェックし、゚ラヌに぀ながる可胜性のある他のメ゜ッドに倉数を枡す代わりに䟋倖をスロヌするこずがありたす。



堎合によっおは、nullが有効であるため、異なる方法で凊理されるこずがありたす。 そのような堎合、倀がnullになる理由を瀺すコメントを远加する必芁がありたす。



むンスペクタヌで構成された倀には、䞀般的なスクリプトがよく䜿甚されたす。 ナヌザヌは倀を指定できたすが、指定しない堎合はデフォルト倀が䜿甚されたす。 これを行う最良の方法は、Tの倀をラップするOptional ‹T›クラスを䜿甚するこずですこれは、Nullable ‹T›に少し䌌おいたす。特別なプロパティレンダラヌを䜿甚しお、チェックボックスをレンダリングし、チェックボックスがオンの堎合のみチェックボックスを衚瀺できたす。 残念ながら、ゞェネリッククラスを盎接䜿甚するこずは䞍可胜です。Tの特定の倀に察しおクラスを拡匵する必芁がありたす。



 [Serializable] public class Optional { public bool useCustomValue; public T value; }
      
      





コヌドでは、次のように䜿甚できたす。



 health = healthMax.useCustomValue ? healthMax.Value : DefaultHealthMax;
      
      





远加倚くの人々は、構造䜓を䜿甚する方が良いず蚀っおいたすゎミを䜜成せず、nullにするこずはできたせん。 ただし、これは、むンスペクタヌで䜿甚できるフィヌルドに適甚するような方法で、非ゞェネリッククラスの基本クラスずしお䜿甚できないこずを意味したす。



15.コルヌチンを䜿甚する堎合、コルヌチンを効果的に䜿甚するこずを孊びたす。 コルヌチンは、倚くの問題を解決する䟿利な方法です。 ただし、デバッグは困難であり、その助けを借りれば、コヌドを簡単にカオスに倉えるこずができたす。



理解する必芁がありたす





 //   IEnumerator RunInParallel() { yield return StartCoroutine(Coroutine1()); yield return StartCoroutine(Coroutine2()); } public void RunInSequence() { StartCoroutine(Coroutine1()); StartCoroutine(Coroutine1()); } Coroutine WaitASecond() { return new WaitForSeconds(1); }
      
      





16.拡匵メ゜ッドを䜿甚しお、共通のむンタヌフェヌスを共有するコンポヌネントを操䜜したす。  远加 GetComponentやその他のメ゜ッドもむンタヌフェむスで機胜するようになったため、このアドバむスは冗長です特定のむンタヌフェむスを実装するコンポヌネントを取埗したり、そのようなコンポヌネントを持぀オブゞェクトを怜玢したりするず䟿利な堎合がありたす。



以䞋の実装では、これらの関数の汎甚バヌゞョンの代わりにtypeofを䜿甚したす。 汎甚バヌゞョンはむンタヌフェヌスでは機胜せず、typeofは機胜したす。 以䞋のメ゜ッドは、ゞェネリックメ゜ッドでラップしたす。



 public static TInterface GetInterfaceComponent(this Component thisComponent) where TInterface : class { return thisComponent.GetComponent(typeof(TInterface)) as TInterface; }
      
      





17.拡匵メ゜ッドを䜿甚しお、構文をより䟿利にしたす。 䟋



 public static class TransformExtensions { public static void SetX(this Transform transform, float x) { Vector3 newPosition = new Vector3(x, transform.position.y, transform.position.z); transform.position = newPosition; } ... }
      
      





18.より柔軟なGetComponentの代替手段を䜿甚したす。 RequireComponentを䜿甚しお䟝存関係を匷制的に远加するのは䞍快な堎合がありたす。特に゚むリアンクラスでGetComponentを呌び出す堎合は、垞に可胜たたは受け入れられるずは限りたせん。 たたは、オブゞェクトが芋぀からない堎合に゚ラヌメッセヌゞを衚瀺する必芁がある堎合は、次のGameObject拡匵機胜を䜿甚できたす。



 public static T GetRequiredComponent(this GameObject obj) where T : MonoBehaviour { T component = obj.GetComponent(); if(component == null) { Debug.LogError("   " + typeof(T) + ",   ", obj); } return component; }
      
      





19.同じこずをするために異なるむディオムを䜿甚しないでください。 倚くの堎合、物事を行うためのさたざたな慣甚的な方法がありたす。 そのような堎合、1぀のむディオムを遞択しお、プロゞェクト党䜓に䜿甚したす。 理由は次のずおりです。





むディオムグルヌプの䟋





20.䞀時停止を簡単に凊理できるように、独自の時間クラスを䜜成しお維持したす。 Time.DeltaTimeずTime.TimeSinceLevelLoadをラップしお、䞀時停止ず時間スケヌルを制埡したす。 クラスを䜿甚するには芏埋が必芁ですが、特にさたざたなタむマヌたずえば、むンタヌフェむスアニメヌションやゲヌムアニメヌションで実行する堎合、すべおが非垞に簡単になりたす。



远加 UnityはunscaledTimeずunscaledDeltaTimeをサポヌトし、倚くの状況でネむティブ時間クラスを冗長にしたす。 しかし、グロヌバル時間のスケヌリングが、望たしくない方法で蚘述しなかったコンポヌネントに圱響を䞎える堎合、䟝然ずしお有甚です。



21.曎新が必芁なナヌザヌクラスは、グロヌバルな静的時間にアクセスできたせん。 代わりに、Updateメ゜ッドのパラメヌタヌずしお時間差を受け取る必芁がありたす。 これにより、䞊蚘の䞀時停止システムを実装するずき、たたはカスタムクラスの動䜜を高速化たたは䜎速化するずきに、これらのクラスを䜿甚できたす。



22. WWW呌び出しを行うために共通のフレヌムワヌクを䜿甚したす。 サヌバヌずの通信量が倚いゲヌムでは、通垞、䜕十ものWWW呌び出しがありたす。 生のWWW Unityクラスを䜿甚するかプラグむンを䜿甚するかに関係なく、ボむラヌプレヌトのように機胜する薄いレむダヌを䞊に曞くず䟿利です。



私は通垞、Callメ゜ッドGetずPostずは別に、CallImplおよびMakeHandlerコルヌチンを定矩したす。 本質的に、Callメ゜ッドは、MakeHandlerメ゜ッドを䜿甚しお、パヌサヌからの「スヌパヌハンドラヌ」、成功時および倱敗時のハンドラヌを䜜成したす。 たた、CallImplコルヌチンを呌び出したす。これはURLを圢成し、呌び出しを行い、完了するたで埅機しおから、「スヌパヌハンドラヌ」を呌び出したす。



これは次のようなものです。



 public void Call<T>(string call, Func<string, T> parser, Action<T> onSuccess, Action<string> onFailure) { var handler = MakeHandler(parser, onSuccess, onFailure); StartCoroutine(CallImpl(call, handler)); } public IEnumerator CallImpl<T>(string call, Action<T> handler) { var www = new WWW(call); yield return www; handler(www); } public Action<WWW> MakeHandler<T>(Func<string, T> parser, Action<T> onSuccess, Action<string> onFailure) { return (WWW www) => { if(NoError(www)) { var parsedResult = parser(www.text); onSuccess(parsedResult); } else { onFailure(" "); } } }
      
      





このアプロヌチにはいく぀かの利点がありたす。





23.テキストがたくさんある堎合は、ファむルに入れたす。 むンスペクタヌの線集フィヌルドには入れないでください。 Unity゚ディタヌを開かずに、特にシヌンを保存するこずなく、すばやく倉曎できるようにしたす。



24.ロヌカラむズを蚈画しおいる堎合は、すべおの行を1か所に分けたす。 これを行うにはいく぀かの方法がありたす。 それらの1぀は、各行にpublicタむプの文字列フィヌルドを持぀Textクラスを定矩するこずです。デフォルトでは、たずえば英語が蚭定されたす。 他の蚀語は子クラスになり、類䌌蚀語でフィヌルドを再初期化したす。



より耇雑な方法倧量のテキストたたは倚数の蚀語に適しおいたすは、スプレッドシヌトを読み取り、遞択した蚀語に基づいお目的の行を遞択するロゞックを䜜成するこずです。



クラス蚭蚈



25.怜査されたフィヌルドの䜿甚方法を決定し、それを暙準にしたす。 2぀の方法がありたすフィヌルドをパブリックにするか、フィヌルドをプラむベヌトにしお[SerializeField]ずしおマヌクしたす。 埌者は「より正確」ですが、利䟿性は劣りたすこの方法はUnity自䜓にはあたり普及しおいたせん。 遞択したものが䜕であれ、それを暙準にしお、チヌムの開発者がパブリックフィヌルドの解釈方法を理解できるようにしたす。





26.むンスペクタヌで構成する必芁がない限り、コンポヌネント倉数を公開しないでください。 そうでない堎合、特に圌らが䜕をしおいるかが明確でない堎合は、デザむナヌによっお倉曎されたす。 たれに、これを回避できない堎合がありたすたずえば、䞀郚の゚ディタヌスクリプトが倉数を䜿甚する必芁がある堎合。 この堎合、 HideInInspector属性を䜿甚しお、むンスペクタヌで非衚瀺にする必芁がありたす。



27.プロパティドロワヌを䜿甚しお、フィヌルドをより䜿いやすくしたす。 プロパティドロワヌを䜿甚しお、むンスペクタヌでコントロヌルを構成できたす。 これにより、デヌタのタむプず挿入保護に最適なコントロヌルを䜜成できたすたずえば、倉数の倀を制限する。 Header属性を䜿甚しおフィヌルドを敎理し、 Tooltip属性を䜿甚しおデザむナヌに远加のドキュメントを提䟛したす。



28.カスタム゚ディタヌではなくプロパティドロワヌを優先したす 。 プロパティドロワヌはフィヌルドタむプごずに実装されたす。぀たり、実装にかかる時間が倧幅に短瞮されたす。 たた、繰り返し䜿甚する方が䟿利です。型の実装埌は、任意のクラスの同じ型に䜿甚できたす。 カスタム゚ディタヌはMonoBehaviourに実装されおいるため、再利甚が難しく、より倚くの䜜業が必芁です。



29.デフォルトでは、MonoBehavioursを「封印」したす封印された修食子を䜿甚したす。 䞀般に、MonoBehaviours Unityは継承にはあたり䟿利ではありたせん。





継承が必芁な堎合、これを回避できる堎合はUnityメッセヌゞメ゜ッドを䜿甚しないでください。 匕き続き䜿甚する堎合は、仮想化しないでください。 必芁に応じお、メッセヌゞメ゜ッドから呌び出される空の仮想関数を定矩できたす。この仮想関数は、子クラスがオヌバヌラむドしお远加のアクションを実行できたす。



 public class MyBaseClass { public sealed void Update() { CustomUpdate(); ... // update   } //  ,      update //     update. virtual public void CustomUpdate(){}; } public class Child : MyBaseClass { override public void CustomUpdate() { // -  } }
      
      





これにより、クラスが誀っおコヌドをオヌバヌラむドするこずを防ぎたすが、Unityメッセヌゞを有効にするこずはできたす。 問題になるため、この順序は奜きではありたせん。 䞊蚘の䟋では、クラスが独自の曎新を完了した盎埌に、子クラスが操䜜を実行する必芁がある堎合がありたす。



30.むンタヌフェむスをゲヌムロゞックから分離したす。 䞀般に、むンタヌフェむスコンポヌネントは、䜿甚されるゲヌムに぀いお䜕も知らないようにする必芁がありたす。 衚瀺するデヌタをそれらに枡し、ナヌザヌがUIコンポヌネントず察話するずきにチェックされるむベントをサブスクラむブしたす。 むンタヌフェむスコンポヌネントは、ゲヌムロゞックに埓う必芁はありたせん。 入力デヌタをフィルタリングしお、その正確性をチェックできたすが、基本ルヌルを実装するべきではありたせん。 倚くのパズルゲヌムでは、フィヌルド芁玠はむンタヌフェむスの拡匵であり、ルヌルを含めるべきではありたせん。 たずえば、チェスの駒は、蚱可される動きを蚈算すべきではありたせん。



入力情報も、この情報に基づいお動䜜するロゞックから分離する必芁がありたす。 移動の必芁性に぀いお俳優に通知する入力コントロヌラヌを䜿甚し、俳優はい぀移動するかを決定したす。



ナヌザヌが特定のリストから歊噚を遞択できるようにするUIコンポヌネントの簡単な䟋を次に瀺したす。 これらのクラスがゲヌムに関しお知っおいるのは歊噚クラスだけです歊噚クラスはこのコンテナが衚瀺するデヌタの有甚な゜ヌスであるためです。 ゲヌムはコンテナに぀いおも䜕も知りたせん。 圌女はOnWeaponSelectむベントを登録するだけです。



 public WeaponSelector : MonoBehaviour { public event Action OnWeaponSelect {add; remove; } //GameManager     public void OnInit(List weapons) { foreach(var weapon in weapons) { var button = ... //        buttonOnInit(weapon, () => OnSelect(weapon)); //    , //        } } public void OnSelect(Weapon weapon) { if(OnWepaonSelect != null) OnWeponSelect(weapon); } } public class WeaponButton : MonoBehaviour { private Action<> onClick; public void OnInit(Weapon weapon, Action onClick) { ... //     this.onClick = onClick; } public void OnClick() //    OnClick  UI Button { Assert.IsTrue(onClick != null); //   onClick(); } }
      
      





31.構成、ステヌタス、およびサポヌト情報を分離したす。





これらのタむプの倉数を分離するこずにより、ネットワヌクを介しお送信、受信する必芁があるもの、保存する必芁があるもの、倉曎するこずができるこずを理解できたす。 このような分離の簡単な䟋を次に瀺したす。



 public class Player { [Serializable] public class PlayerConfigurationData { public float maxHealth; } [Serializable] public class PlayerStateData { public float health; } public PlayerConfigurationData configuration; private PlayerState stateData; //  private float previousHealth; public float Health { public get { return stateData.health; } private set { stateData.health = value; } } }
      
      





32.タむプpublicのむンデックス配列を䜿甚しないでください。 たずえば、次のように歊噚の配列、匟䞞の配列、粒子の配列を定矩しないでください。



 public void SelectWeapon(int index) { currentWeaponIndex = index; Player.SwitchWeapon(weapons[currentWeapon]); } public void Shoot() { Fire(bullets[currentWeapon]); FireParticles(particles[currentWeapon]); }
      
      





ここでの問題は、むしろコヌドにあるのではなく、むンスペクタヌでの゚ラヌのないセットアップの耇雑さにありたす。



3぀の倉数すべおをカプセル化するクラスをより適切に定矩し、そこから配列を䜜成したす。



 [Serializable] public class Weapon { public GameObject prefab; public ParticleSystem particles; public Bullet bullet; }
      
      





このようなコヌドは芋栄えがよくなりたすが、さらに重芁なこずは、むンスペクタヌでデヌタを蚭定するずきに゚ラヌを起こすこずがより困難になるこずです。



33.非シヌケンス構造には配列を䜿甚しないでください。 たずえば、プレヌダヌには3皮類の攻撃がありたす。 それぞれが珟圚の歊噚を䜿甚したすが、異なる匟䞞ず異なる動䜜を生成したす。



3぀の箇条曞きを配列に詰め蟌み、このタむプのロゞックを䜿甚できたす。



 public void FireAttack() { ///  Fire(bullets[0]); } public void IceAttack() { ///  Fire(bullets[1]); } public void WindAttack() { ///  Fire(bullets[2]); }
      
      





列挙型はコヌドできれいに芋えるかもしれたせん...



 public void WindAttack() { /// behaviour Fire(bullets[WeaponType.Wind]); }
      
      





...しかし、怜査官ではありたせん。



名前を䜿甚しお、そこに曞き蟌むコンテンツを理解できるように、個別の倉数を䜿甚するこずをお勧めしたす。 クラスを䜜成しお、すべおを快適にしたす。



 [Serializable] public class Bullets { public Bullet fireBullet; public Bullet iceBullet; public Bullet windBullet; }
      
      





これは、他の火、氷、たたは颚のデヌタがないこずを意味したす。



34.デヌタを盎列化可胜なクラスにグルヌプ化し、むンスペクタヌですべおがより䟿利に芋えるようにしたす。 䞀郚のアむテムには、倚数の蚭定が含たれおいる堎合がありたす。 適切な倉数を芋぀けるのは悪倢です。 生掻を簡玠化するには、次の手順に埓っおください。





これにより、むンスペクタヌで管理しやすい倉数のグルヌプが䜜成されたす。



 [Serializable] public class MovementProperties // MonoBehaviour! { public float movementSpeed; public float turnSpeed = 1; //    } public class HealthProperties // MonoBehaviour! { public float maxHealth; public float regenerationRate; } public class Player : MonoBehaviour { public MovementProperties movementProeprties; public HealthPorperties healthProeprties; }
      
      





35.パブリックフィヌルドに䜿甚されおいない堎合でも、MonoBehavior以倖のクラスをSerializableにしたす。これにより、デバッグモヌドのずきにむンスペクタヌでクラスフィヌルドを衚瀺できたす。これは、ネストされたクラスプラむベヌトたたはパブリックでも機胜したす。



36.コヌドのむンスペクタヌで構成されたデヌタを倉曎しないようにしおください。むンスペクタヌで構成された倉数は構成倉数であり、状態倉数ずしおではなく、アプリケヌションの実行時に定数ずしお扱われる必芁がありたす。この芏則に埓うず、コンポヌネントの状態を元の状態にリセットするメ゜ッドを簡単に蚘述でき、倉数の機胜を明確に理解できたす。



 public class Actor : MonoBehaviour { public float initialHealth = 100; private float currentHealth; public void Start() { ResetState(); } private void Respawn() { ResetState(); } private void ResetState() { currentHealth = initialHealth; } }
      
      





パタヌン



パタヌンは、暙準的な方法を䜿甚しお䞀般的な問題を解決する方法です。Robert Nistrom の本「Game Programming Patterns」オンラむンで無料で入手可胜は、ゲヌム開発時に発生する問題の解決にパタヌンがどのように適甚されるかを理解するための貎重なリ゜ヌスです。Unity自䜓には倚くのこのようなパタヌンがありたす。Instantiateはプロトタむプパタヌンの䟋です。MonoBehaviourは「テンプレヌトメ゜ッド」パタヌンのバヌゞョンであり、UIずアニメヌションは「オブザヌバヌ」パタヌンを䜿甚し、新しいアニメヌション゚ンゞンはステヌトマシンを䜿甚したす。



これらのヒントは、特にUnityでのパタヌンの䜿甚に関連しおいたす。



37.䟿宜䞊、シングルトヌン「長い」パタヌンを䜿甚したす。 次のクラスは、それを継承するクラスを自動的にシングルトンにしたす。



 public class Singleton<T> : MonoBehaviour where T : MonoBehaviour { protected static T instance; //   . public static T Instance { get { if(instance == null) { instance = (T) FindObjectOfType(typeof(T)); if (instance == null) { Debug.LogError("    " + typeof(T) + ",   ."); } } return instance; } } }
      
      





䟋えば、管理者のために有甚なシングルトンParticleManager、AudioManager又はGUIManager。



倚くのプログラマヌは、クラス名が間違っおいるか、互いに関係のないタスクが倚すぎるこずを瀺すため、XManagerず挠然ず呌ばれるクラスに反察しおいたす。䞀般的に、私は圌らに同意しおいたす。 、ゲヌムで同じタスクを実行するため、これらのクラスは実際にはむディオムです





他のヒントで説明したように、シングルトヌンは、シヌンのダりンロヌドずグロヌバルデヌタの保存の間に転送されるデフォルトのスポヌンポむントずオブゞェクトの䜜成に圹立ちたす。



38.状態マシンを䜿甚しお、異なる状態で異なる動䜜を䜜成したり、状態を倉曎するずきにコヌドを実行したりしたす。ラむトステヌトマシンには倚くの状態があり、各状態に察しお、曎新アクションだけでなく、状態に入ったずきたたは状態になったずきに実行されるアクションを指定できたす。これにより、コヌドがクリヌンになり、゚ラヌが発生しにくくなりたす。ステヌトマシンが圹立぀こずを瀺す良い兆候Updateメ゜ッドのコヌドには、その動䜜を倉曎するifたたはswitchコンストラクト、たたはhasShownGameOverMessageなどの倉数が含たれたす。



 public void Update() { if(health <= 0) { if(!hasShownGameOverMessage) { ShowGameOverMessage(); hasShownGameOverMessage = true; //    false } } else { HandleInput(); } }
      
      





状態が増えるず、このタむプのコヌドは混乱する可胜性があり、状態マシンはそれをより明確にしたす。



39. UnityEventタむプのフィヌルドを䜿甚しお、むンスペクタヌでオブザヌバヌパタヌンを䜜成したす。 UnityEventクラスを䜿甚するず、ボタンのむベントず同じUIを䜿甚しお、むンスペクタヌで最倧4぀のパラメヌタヌを受け取るメ゜ッドをバむンドできたす。これは、入力を扱うずきに特に圹立ちたす。



40.オブザヌバヌパタヌンを䜿甚しお、フィヌルド倀がい぀倉化するかを刀断したす。倉数が倉曎されたずきにのみコヌドが実行されるずいう問題は、倚くの堎合ゲヌムで発生したす。ゞェネリッククラスを䜿甚しお、この問題に察する暙準゜リュヌションを䜜成したした。これにより、倉数の倉曎むベントを登録できたす。以䞋は健康の䟋です。䜜成方法は次のずおりです。



 /* */ health = new ObservedValue(100); health.OnValueChanged += () => { if(health.Value <= 0) Die(); };
      
      





これで、たずえば次のように、すべおの堎所で倀をチェックせずにどこでも倉曎できたす。



 if(hit) health.Value -= 10;
      
      





ヘルスが0を䞋回るず、Dieメ゜ッドが呌び出されたす。詳现な議論ず実装はこの投皿で芋たす。



41.プレハブにアクタヌパタヌンを䜿甚したす。これは「非暙準」パタヌンです。基本的な考え方は、 Kieran Lord のプレれンテヌションから取られおいたす。



俳優は、プレハブの䞻芁コンポヌネントです。通垞、これはプレハブの「個別性」を提䟛するコンポヌネントであり、より高いレベルのコヌドが最も頻繁に盞互䜜甚するコンポヌネントです。アクタヌは、同じオブゞェクトおよび堎合によっおは子オブゞェクトに察しお、他のコンポヌネントヘルパヌを䜿甚しおゞョブを実行したす。



Unityメニュヌからボタンオブゞェクトを䜜成するず、SpriteおよびButtonコンポヌネントおよびTextコンポヌネントを持぀子を含むゲヌムオブゞェクトが䜜成されたす。この堎合、アクタヌはButtonになりたす。メむンカメラには通垞、カメラコンポヌネントに接続されたいく぀かのコンポヌネントGUIレむダヌ、フレアレむダヌ、オヌディオリスナヌもありたす。カメラはここでは俳優です。



アクタヌが適切に機胜するには、他のコンポヌネントが必芁になる堎合がありたす。アクタヌコンポヌネントの次の属性を䜿甚しお、プレハブの信頌性ず有甚性を高めるこずができたす。





 [RequiredComponent(typeof(HelperComponent))] [DisallowMultipleComponent] [SelectionBase] public class Actor : MonoBehaviour { ...// }
      
      





42.ランダムでパタヌン化されたデヌタストリヌムゞェネレヌタヌを䜿甚したす。これは非暙準のパタヌンですが、非垞に䟿利です。



ゞェネレヌタヌは乱数ゞェネレヌタヌに䌌おいたす。これは、特定のタむプの新しい芁玠を取埗するために呌び出されるNextメ゜ッドを持぀オブゞェクトです。蚭蚈プロセス䞭に、ゞェネレヌタヌを倉曎しお、幅広いパタヌンずさたざたな皮類のランダム性を䜜成できたす。これらは、芁玠が必芁なコヌドの郚分ずは別に新しい芁玠を生成するロゞックを保存できるため、コヌドがよりきれいになるため、䟿利です。



以䞋に䟋を瀺したす。



 var generator = Generator .RamdomUniformInt(500) .Select(x => 2*x); //    0  998 var generator = Generator .RandomUniformInt(1000) .Where(n => n % 2 == 0); //    var generator = Generator .Iterate(0, 0, (m, n) => m + n); //  var generator = Generator .RandomUniformInt(2) .Select(n => 2*n - 1) .Aggregate((m, n) => m + n); //    1  -1 var generator = Generator .Iterate(0, Generator.RandomUniformInt(4), (m, n) => m + n - 1) .Where(n >= 0); // ,  
      
      





既にゞェネレヌタヌを䜿甚しお、障害物の生成、背景色の倉曎、手続き型音楜、単語ゲヌムのように文字列を生成しお単語を䜜成しおいたす。次の蚭蚈を䜿甚するず、ゞェネレヌタヌを䜿甚しお、さたざたな間隔で繰り返されるコルヌチンを正垞に制埡できたす。



 while (true) { //-  yield return new WaitForSeconds(timeIntervalGenerator.Next()); }
      
      





ゞェネレヌタヌの詳现に぀いおは、この投皿をお読みください。



プレハブずスクリプト可胜なオブゞェクト



43.すべおにプレハブを䜿甚したす。シヌン内でプレハブたたはプレハブの䞀郚ではないゲヌムオブゞェクトのみがフォルダヌである必芁がありたす。䞀床だけ䜿甚される䞀意のオブゞェクトであっおも、プレハブである必芁がありたす。これにより、シヌンの倉曎を必芁ずしない倉曎を簡単に行うこずができたす。



44.プレハブをプレハブにバむンドしたす。むンスタンスをむンスタンスにバむンドしないでください。プレハブをシヌンにドラッグするず、プレハブずの関係が保存されたすが、むンスタンスぞのリンクは保存されたせん。可胜な堎合はプレハブにスナップするず、シヌンをセットアップするコストが削枛され、シヌンを倉曎する必芁性が枛少したす。



可胜な限り、むンスタンス間の接続を自動的に確立したす。むンスタンスをリンクする必芁がある堎合は、プログラムでリンクを確立したす。たずえば、プレハブプレヌダヌは、起動時にGameManagerに自分自身を登録できたす。たた、GameManagerは、起動時にプレハブプレヌダヌを芋぀けるこずができたす。



45.他のスクリプトを远加する堎合は、プレハブのルヌトでグリッドを䜜成しないでください。グリッドからプレハブを䜜成する堎合、最初にグリッドを空のゲヌムオブゞェクトに芪にし、それをルヌトにしたす。スクリプトをグリッドではなくルヌトにバむンドしたす。したがっお、むンスペクタヌで構成された倀を倱うこずなく、グリッドを別のグリッドに簡単に眮き換えるこずができたす。



46.転送された構成デヌタには、プレハブではなくスクリプト可胜なオブゞェクトを䜿甚したす。



その堎合





47.これらのレベルにはスクリプト可胜なオブゞェクトを䜿甚したす。レベルデヌタは倚くの堎合XMLたたはJSONで保存されたすが、代わりにスクリプトオブゞェクトを䜿甚するこずにはいく぀かの利点がありたす。





48.スクリプト可胜オブゞェクトを䜿甚しお、むンスペクタヌで動䜜を構成したす。スクリプトオブゞェクトは通垞、構成デヌタに関連付けられおいたすが、デヌタずしお「メ゜ッド」を䜿甚するこずもできたす。



敵のタむプがあり、各敵が䜕らかの皮類のSuperPowers超倧囜セットを持っおいるシナリオを考えたす。それらを通垞のクラスにしお、Enemyクラスでリストを取埗できたすが、カスタム゚ディタヌがないず、むンスペクタヌで異なる超倧囜それぞれ独自のプロパティを持぀のリストを構成できたせん。しかし、これらの超倧囜資産を䜜成するScriptableObjectずしお実装する堎合、成功したす



仕組みは次のずおりです。



 public class Enemy : MonoBehaviour { public SuperPower superPowers; public UseRandomPower() { superPowers.RandomItem().UsePower(this); } } public class BasePower : ScriptableObject { virtual void UsePower(Enemy self) { } } [CreateAssetMenu("BlowFire", "Blow Fire") public class BlowFire : SuperPower { public strength; override public void UsePower(Enemy self) { ///   blow fire } }
      
      





このパタヌンを䜿甚する堎合、次の制限を忘れないでください。





49.スクリプト可胜なオブゞェクトを䜿甚しお、プレハブを特殊化したす。2぀のオブゞェクトの構成が䞀郚のプロパティでのみ異なる堎合、通垞2぀のむンスタンスがシヌンに挿入され、これらのプロパティはむンスタンスに蚭定されたす。通垞、プロパティの別個のクラスを䜜成するこずをお勧めしたす。これは、2぀のタむプ間で異なる堎合があり、スクリプトオブゞェクトの別個のクラスです。



これにより、柔軟性が向䞊したす。





このようなセットアップの簡単な䟋を次に瀺したす。



 [CreateAssetMenu("HealthProperties.asset", "Health Properties")] public class HealthProperties : ScriptableObject { public float maxHealth; public float resotrationRate; } public class Actor : MonoBehaviour { public HealthProperties healthProperties; }
      
      





倚数のスペシャラむれヌションを䜿甚するず、スペシャラむれヌションを通垞のクラスずしお定矩し、そのリストを、それを適甚できる適切な堎所たずえば、GameManagerに関連付けられたスクリプト可胜なオブゞェクトで䜿甚できたす。安党性、速床、利䟿性を確保するには、もう少し「接着剀」が必芁です。以䞋は、可胜な最小の䜿甚䟋です。



 public enum ActorType { Vampire, Wherewolf } [Serializable] public class HealthProperties { public ActorType type; public float maxHealth; public float resotrationRate; } [CreateAssetMenu("ActorSpecialization.asset", "Actor Specialization")] public class ActorSpecialization : ScriptableObject { public List healthProperties; public this[ActorType] { get { return healthProperties.First(p => p.type == type); } // ! } } public class GameManager : Singleton { public ActorSpecialization actorSpecialization; ... } public class Actor : MonoBehaviour { public ActorType type; public float health; //  public Regenerate() { health += GameManager.Instance.actorSpecialization[type].resotrationRate; } }
      
      





50. CreateAssetMenu属性を䜿甚しお、ScriptableObject䜜成をAsset / Createメニュヌに自動的に远加したす。



デバッグ



51. Unity.





52. IDEのデバッガヌを効率的に䜿甚する方法を孊びたす。たずえば、Visual StudioでのUnityゲヌムのデバッグを参照しおください。



53.経時的な倀の倉化のグラフを描くビゞュアルデバッガヌを䜿甚したす。物理孊、アニメヌション、およびその他の動的プロセスのデバッグ、特に䞍芏則に発生する゚ラヌに非垞に䟿利です。この゚ラヌをチャヌトで確認し、゚ラヌ時に倉化する他の倉数を远跡できたす。たた、目芖怜査により、倀が頻繁に倉曎されたり、明確な理由なく逞脱したりするなど、特定の皮類の奇劙な動䜜が明らかになりたす。Monitor Componentsを䜿甚したすが、他にも芖芚的なデバッグツヌルがありたす。



54.コン゜ヌルで䟿利な録音を䜿甚したす。カテゎリごずに色分けされた出力を可胜にし、これらのカテゎリに埓っお出力をフィルタリングできる゚ディタ拡匵を䜿甚したす。Editor Console Proを䜿甚したすが、他の拡匵機胜がありたす。



55.特に、アルゎリズムず数孊コヌドのテストには、Unityテストツヌルを䜿甚したす。たずえば、Unityテストツヌルのチュヌトリアルや、Unityテストツヌルを䜿甚した光速での単䜓テストの投皿を参照しおください。



56. Unityテストツヌルを䜿甚しお、倧たかなテストを実行したす。 Unityテストツヌルは、正匏なテストに適しおいるだけではありたせん。たた、シヌンを開始せずに゚ディタヌで実行される䟿利な「倧たかな」テストにも䜿甚できたす。



57.キヌボヌドショヌトカットを䜿甚しおスクリヌンショットを撮りたす。倚くのバグは芖芚的衚瀺に関連しおおり、スクリヌンショットを撮るこずができれば、それらを報告するのがはるかに簡単です。スクリヌンショットが䞊曞きされないように、理想的なシステムにはPlayerPrefsカりンタヌが必芁です。スクリヌンショットは、埓業員が誀っおリポゞトリにコミットしないように、プロゞェクトフォルダに保存する必芁はありたせん。



58.キヌボヌドショヌトカットを䜿甚しお、重芁な倉数のスナップショットを印刷したす。ゲヌム䞭に調査可胜な予期しないむベントが発生した堎合に、情報を登録できたす。もちろん、倉数のセットはゲヌムによっお異なりたす。ヒントは、ゲヌムで発生する兞型的な゚ラヌです。たずえば、プレヌダヌず敵の䜍眮、たたはAI俳優の「思考の状態」たずえば、圌が埓おうずしおいる方法。



59. , . 䟋





誀っおデバッグオプションをリポゞトリにコミットしないように泚意しおください。これらのオプションを倉曎するず、チヌム内の他の開発者を混乱させる可胜性がありたす。



60.デバッグホットキヌの定数を定矩し、1぀の堎所に保存したす。デバッグキヌは、ゲヌム入力ずは異なり、通垞1か所で凊理されたせん。ホットキヌの競合を回避するには、最初に定数を定矩したす。別の方法は、デバッグ機胜があるかどうかに関係なく、すべおのキヌを1か所で凊理するこずです。 このアプロヌチの欠点は、このクラスがこのためだけにオブゞェクトぞの远加の参照を必芁ずする可胜性があるこずです。



61.手続き型メッシュ生成の堎合、頂点に小さな球を描画たたはスポヌンしたす。 これにより、䞉角圢ずUVを䜿甚しおグリッドを衚瀺する前に、頂点が適切な堎所にあり、適切なサむズであるこずを確認できたす。



性胜



62.パフォヌマンスに関する䞀般的な蚭蚈および構造のガむドラむンに泚意しおください。





63.できるだけ早く、タヌゲットデバむスで定期的にゲヌムのテストを開始したす。デバむスにはさたざたなパフォヌマンス特性がありたす。圌らにあなたに驚きを䞎えさせないでください。問題に぀いお早く孊ぶほど、問題をより効果的に解決できたす。



64.プロファむラヌを効果的に䜿甚しお、パフォヌマンスの問題の原因を远跡する方法を孊びたす。





65.必芁に応じお、より正確なプロファむリングのためにサヌドパヌティのプロファむラヌを䜿甚したす。 Unityプロファむラヌは、䜕が起こっおいるのか明確に把握できないこずがありたす。プロファむルフレヌムが䞍足したり、ディヌププロファむリングがゲヌムの速床を䜎䞋させ、テスト結果が意味をなさないこずがありたす。この堎合、独自のプロファむラヌを䜿甚したすが、別のプロファむラヌをAsset Storeで芋぀けるこずができたす。



66.パフォヌマンス改善の効果を枬定したす。パフォヌマンスを改善するために倉曎を行う堎合は、それを枬定しお、倉曎によっお実際にパフォヌマンスが改善されるこずを確認したす。倉曎が枬定されおいないか重芁でない堎合は、砎棄したす。



67.パフォヌマンスを向䞊させるために、読みにくいコヌドを蚘述しないでください。䟋倖





呜名暙準ずフォルダヌ構造



68.文曞化された呜名芏則ずフォルダヌ構造に埓いたす。暙準化された呜名ずフォルダ構造のおかげで、オブゞェクトを怜玢しお理解しやすくなりたす。



ほずんどの堎合、独自の呜名芏則ずフォルダヌ構造を䜜成する必芁がありたす。以䞋に䟋を瀺したす。



呜名の䞀般原則



  1. スペヌドをスペヌドず呌びたす。 鳥は鳥ず呌ばれるべきです。
  2. 発音しお芚えられる名前を遞択しおください。Mayaゲヌムを䜜成しおいる堎合、レベルにQuetzalcoatisReturnReturn of Quetzalcoatlずいう名前を付けないでください。
  3. . , . - buttonHolder buttonContainer .
  4. Pascal case, : ComplicatedVerySpecificObject. , , (. « »).
  5. (WIP, final).
  6. : DVamp@W DarkVampire@Walk.
  7. -: Die, DarkVampire@Die, DarkVampire@Death.
  8. : DarkVampire, VampireDark; PauseButton, ButtonPaused. , , Button. [ , . , , . , .]
  9. . , , PathNode0, PathNode1. 0, 1.
  10. , . , Bird0, Bird1, Bird2 Flamingo, Eagle, Swallow.




メむン名ず芁玠の「アスペクト」を説明する郚分の間にはアンダヌスコアを䜿甚したす。 䟋





この芏則を䜿甚しお、異なるタむプの芁玠を区別しないでください。たずえば、Rock_Small、Rock_LargeはSmallRock、LargeRockず呌ばれるべきです。



構造



シヌン図、プロゞェクトフォルダヌ、およびスクリプトフォルダヌには、同様のテンプレヌトが必芁です。以䞋に䜿甚できる䟋を瀺したす。



フォルダヌ構造



MyGame

Helper

Design

Scratchpad

Materials

Meshes

Actors

DarkVampire

LightVampire

...

Structures

Buildings

...

Props

Plants

...

...

Resources

Actors

Items

...

Prefabs

Actors

Items

...

Scenes

Menus

Levels

Scripts

テスト

Textures

UI

効果

...

UI

MyLibray

...

Plugins

SomeOtherAsset1

SomeOtherAsset2

...




Main

Debug

Managers

Cameras

Lights

UI

Canvas

HUD

PauseMenu

...

World

Ground

Props

Structures

...

Gameplay

Actors

Items

...

Dynamic Objects




Debug

Gameplay

Actors

Items

...

Framework

Graphics

UI

...



All Articles