[Unityプロジェクト最適化コレクション]コードレベルの最適化と回避

Unity業界のQQ交換グループへようこそ:956187480

1つ:コード効率を改善する

1.ループ本体コードを単純化するために、可能な限り少ないループロジックを使用します(While、for、foreach、recursion)

ビジネス要件のレベルでループロジックを回避するようにしてください。ループロジックが本当に必要な場合は、ロジックを明確にしてください。メインループ本体のコードに冗長変数や冗長メモリを使用することはできません。更に:

for(int i=0;i<myArray.Length;i++)//避免

int length=myArray.Length;  
for(int i=0;i<length;i++) //提倡

2.ライフサイクル関数UpdateおよびLateUpdataを上手に使用します。

Updataの各フレームとLateUpdataの固定フレームの機能の意味を明確にする両方を使用する場合、現在の需要に高頻度の実行呼び出しが必要かどうかを明確にする必要があります。フレームごとに呼び出しを実行する必要がある場合、または論理的に実行する必要がある場合単一フレームで処理する場合(画面レンダリングなど)、Updataを使用します。さらに、更新の実行頻度(物理的な変位の回転やその他のロジックなど)の要件が高くない場合は、LateUpdataを使用できます。 ;空のUpdateメソッドを削除します

    void Update()
    {
        if (isTrue) { isTrue = false;}//一定要加条件保护
    }
    private void LateUpdate()
    {
        transform.Rotate(Vector3.up * Time.fixedDeltaTime * speed);
    }

3.変更が発生した場合にのみコードを実行します(UIインターフェイスデータの更新)。

ほとんどの場合、UIインターフェイスのデータ更新など、ロジックに特別な注意を払う必要はありません。多くの初心者は、UIの更新ロジックを直接Updataに配置することを好みます。これは非常に簡単ですが、インターフェイスデータを個別に管理したり、メンテナンスしたりする必要はありませんが、インターフェイスに大量のデータがあり、頻繁に更新されると、プログラムに多大なレンダリング負荷がかかります。デリゲートやその他の方法を使用して、データが更新された場合にのみ、UIインターフェイスの更新ロジックを呼び出します。

public delegate void MyDelegate(int score);//定义委托
public MyDelegate myDelegate; //声明委托
   
private int score = 0;
public int Score
{
    get => score;
    set
    {
        score = value; myDelegate?.Invoke(score);
    }
}
private void Start()
{
    myDelegate += UpdataUIData;//委托注册事件
}
public void UpdataUIData(int score)
{
    //刷新ui界面数据
}

4.頻繁に実行する必要があり、数フレームごとに実行されるイベントによってトリガーできない方法を変更します。たとえば、前述のlateUpdata固定フレーム。これに加えて、コラボレーションを柔軟に利用でき、最初からコラボレーションを開始できます

private void Start()
{
    InvokeRepeating("RunSomeThing",1,5);//一秒钟执行五次
}
private int interval = 3;//间隔帧
void Update()
{
    if (Time.frameCount % interval == 0)//每三帧执行一次
    {
        RunSomeThing();
    }
}
public void RunSomeThing() { }

5.キャッシュを使用して、フェッチして繰り返し使用する必要のある値を保存します。

。動的に取得されたコンポーネントはグローバル変数に格納できます。使用する場合は、繰り返し取得を回避するために直接フェッチできます
。繰り返し使用される一時変数は、宣言時にグローバルに格納できます
。動的にインスタンス化されたオブジェクト。メソッドは管理が簡単です。次回は直接使用します

6.数値型にfloatを使用することは避け、特にモバイルゲームではintを使用し、sin、cos、その他の関数など、それほど複雑でない数学関数を使用するようにしてください。除算/乗算を変更します。例:x/2.0fの代わりにx*0.5fを使用します。

7.アクティブなガベージコレクション

void Update()
{
    //固定时间GC回收但也不能太频繁,建议跳转场景的时候或者重要模块切换的时候回收
    if (Time.frameCount % 50 == 0)
    {
        GC.Collect();
    }
}

2:高価なUnityAPIを呼び出さないでください

1. SendMessage()とBroadcastMessage()はリフレクションを使用し、リフレクションはより多くのCPUオーバーヘッドを引き起こします。直接呼び出すことも、C#デリゲートを介して呼び出すこともできます。

2. Find()メソッドは、メモリ内の各GameObjectとコンポーネントをトラバースし、プロジェクトの規模が拡大するにつれて、そのオーバーヘッドが増加します。Find()および同様のメソッドの使用を避け、UpdateまたはFixedUpdateで検索メソッドをできるだけ使用しないようにしてください

3. Transformで位置と回転を設定すると、内部のOnTransformChangedイベントがトリガーされ、すべてのサブオブジェクトに伝播されます。サブオブジェクトが大きく異なるオブジェクトの場合、この操作は非常にコストがかかるため、位置と回転の変更を減らす必要があります。メソッドで位置のxyzを個別に設定する場合は、毎回位置のxyzを個別に設定する代わりに、Vector3を作成してからそれぞれxyzをVector3に設定し、最後にVector3を位置に設定できます。 。positionの代わりにlocalPositionを使用してみてください。localPositionはトランスフォームに保存されます。値にアクセスすると、Unityは値を直接返し、アクセスされるたびに位置が再計算されます。位置を頻繁に取得する場合は、キャッシュできます。

4. Update()やLateUpdate()などのイベントメソッドを呼び出すたびに、エンジンコードとマネージコード間の通信が必要になり、メソッド本体であっても、Unityがセキュリティチェック(GameObjectの状態が有効かどうかなど)を実行する必要があります。これらのイベントメソッドの1つがEmptyである場合でも、エンジンはそれを呼び出します。したがって、CPU時間を無駄にしないために、空のイベントメソッドを削除する必要があります。さらに、アクティブ状態(gameObject.active == true)のGameObject上のスクリプトにAwake()メソッドが含まれている場合、スクリプトが有効になっていない(enabled == false)場合でもAwake()メソッドが実行されます。ゲームにUpdate()メソッドを使用したMonoBehaviorsが多数ある場合は、オーバーヘッドを減らすためにコード構造を変更してみてください。関連するブログ投稿があります。

5. Vector2およびVector3()ベクトルの数学演算は、通常の浮動小数点数および整数の演算よりも複雑です。ベクトルの一部のプロパティにアクセスすると、マグニチュードプロパティなどの暗黙のオーバーヘッドが発生する可能性があります(上記)。記事に記載されているTransform.position)。マグニチュードにアクセスするたびに、エンジンは平方根演算を実行します。1回の計算にはそれほど時間はかかりませんが、マグニチュードの次数が十分に大きい場合、このオーバーヘッドが顕著になります。平方根演算を減らすために、大きさの代わりにsqrMagnitude(つまり、大きさの2乗)を使用してみることができます。

6. Camera.mainによって引き起こされる問題は、Find()メソッドに似ています。Camera.mainの使用を避け、カメラへの参照を手動で管理する必要があります。

おすすめ

転載: blog.csdn.net/qq_37310110/article/details/123107938