Recherche…


Remarques

  1. Si possible, désactivez les scripts sur les objets lorsqu'ils ne sont pas nécessaires. Par exemple, si vous avez un script sur un objet ennemi que les utilisateurs recherchent et déclenchent sur le joueur, envisagez de désactiver ce script lorsque l'ennemi est trop éloigné du joueur, par exemple.

Vérifications rapides et efficaces

Évitez les opérations inutiles et les appels de méthodes partout où vous le pouvez, en particulier dans une méthode appelée plusieurs fois par seconde, comme la Update à Update .

Contrôle de distance / distance

Utilisez sqrMagnitude au lieu de l' magnitude lorsque vous comparez les distances. Cela évite inutiles sqrt opérations. Notez que lorsque vous utilisez sqrMagnitude , le côté droit doit également être mis au carré.

if ((target.position - transform.position).sqrMagnitude < minDistance * minDistance))

Chèques de Limites

Les intersections d'objets peuvent être grossièrement vérifiées en vérifiant si leurs limites Collider / Renderer croisent. La structure Bounds a également une méthode pratique Intersects qui permet de déterminer si deux bornes se croisent.

Bounds nous aident également à calculer une approximation proche de la distance réelle (surface à surface) entre les objets (voir Bounds.SqrDistance ).

Mises en garde

La vérification des limites fonctionne très bien pour les objets convexes, mais les vérifications des limites sur les objets concaves peuvent entraîner des inexactitudes beaucoup plus importantes selon la forme de l'objet.

L'utilisation de Mesh.bounds n'est pas recommandée car elle renvoie des limites d'espace locales. Utilisez MeshRenderer.bounds place.

Puissance de coroutine

Usage

Si vous exécutez une opération longue qui repose sur l’API Unity non compatible avec les threads , utilisez Coroutines pour la diviser sur plusieurs cadres et garder votre application réactive.

Les coroutines permettent également d'effectuer des actions coûteuses à chaque nième image au lieu d'exécuter cette action à chaque image.

Fractionnement de routines de longue durée sur plusieurs images

Coroutines permet de distribuer des opérations de longue durée sur plusieurs cadres afin de maintenir le framerate de votre application.

Les routines qui peignent ou génèrent du terrain de manière procédurale ou génèrent du bruit sont des exemples qui peuvent nécessiter le traitement Coroutine.

for (int y = 0; y < heightmap.Height; y++) 
{
    for (int x = 0; x < heightmap.Width; x++)
    {
        // Generate pixel at (x, y)
        // Assign pixel at (x, y)
        
        // Process only 32768 pixels each frame
        if ((y * heightmap.Height + x) % 32 * 1024) == 0)
            yield return null; // Wait for next frame
    }
}

Le code ci-dessus est un exemple facile à comprendre. Dans le code de production , il est préférable d'éviter le contrôle par pixel qui vérifie quand yield return le for yield return (peut - être faire tous les 2-3 lignes) et d' effectuer une pré-calcul for la longueur de boucle à l' avance.

Effectuer des actions coûteuses moins souvent

Les Coroutines vous aident à effectuer des actions coûteuses moins fréquemment, de sorte qu’elles ne sont pas aussi importantes que si elles étaient exécutées à chaque image.

En prenant l'exemple suivant directement à partir du manuel :

private void ProximityCheck() 
{
    for (int i = 0; i < enemies.Length; i++) 
    {
        if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance)
                return true;
    }
    return false;
}

private IEnumerator ProximityCheckCoroutine() 
{
    while(true) 
    {
        ProximityCheck();
        yield return new WaitForSeconds(.1f);
    }
}

Les tests de proximité peuvent être optimisés en utilisant l’ API CullingGroup .

Pièges courants

Une erreur courante des développeurs est d’accéder aux résultats ou aux effets secondaires des coroutines en dehors de la coroutine. Coroutines retourne le contrôle à l'appelant dès qu'un relevé de yield return est rencontré et que le résultat ou l'effet secondaire peut ne pas encore être exécuté. Pour contourner les problèmes où vous devez utiliser le résultat / effet secondaire en dehors de la coroutine, cochez cette réponse .

Cordes

On pourrait faire valoir qu’il ya plus de porcs dans l’Unité que l’humble cordelette, mais c’est l’un des aspects les plus faciles à résoudre dès le départ.

Les opérations de type string créent des ordures

La plupart des opérations sur les chaînes génèrent des quantités infimes de déchets, mais si ces opérations sont appelées plusieurs fois au cours d'une seule mise à jour, elles se cumulent. Au fil du temps, cela déclenchera le nettoyage de la mémoire automatique, ce qui peut entraîner une pointe de processeur visible.

Cachez vos opérations de chaîne

Prenons l'exemple suivant.

string[] StringKeys = new string[] {
    "Key0",
    "Key1",
    "Key2"
};

void Update()
{
    for (var i = 0; i < 3; i++)
    {
        // Cached, no garbage generated
        Debug.Log(StringKeys[i]);
    }

    for (var i = 0; i < 3; i++)
    {
        // Not cached, garbage every cycle
        Debug.Log("Key" + i);
    }

    // The most memory-efficient way is to not create a cache at all and use literals or constants.
    // However, it is not necessarily the most readable or beautiful way.
    Debug.Log("Key0");
    Debug.Log("Key1");
    Debug.Log("Key2");
}

Cela peut sembler idiot et redondant, mais si vous travaillez avec Shaders, vous pourriez rencontrer de telles situations. Cacher les clés fera la différence.

Veuillez noter que les littéraux de chaîne et les constantes ne génèrent aucune erreur, car ils sont injectés de manière statique dans l'espace de pile du programme. Si vous générez des chaînes au moment de l'exécution et que vous générez les mêmes chaînes à chaque fois, comme dans l'exemple ci-dessus, la mise en cache sera certainement utile.

Pour les autres cas où la chaîne générée n'est pas la même à chaque fois, il n'y a pas d'autre alternative à la génération de ces chaînes. En tant que tel, le pic de mémoire avec la génération manuelle de chaînes à chaque fois est généralement négligeable, à moins que des dizaines de milliers de chaînes ne soient générées à la fois.

La plupart des opérations de chaîne sont des messages de débogage

Faire des opérations de chaîne pour les messages de débogage, c.-à-d. Debug.Log("Object Name: " + obj.name) est Debug.Log("Object Name: " + obj.name) et ne peut être évité pendant le développement. Il est toutefois important de veiller à ce que les messages de débogage non pertinents ne se retrouvent pas dans le produit publié.

L'une des méthodes consiste à utiliser l' attribut Conditionnel dans vos appels de débogage. Cela non seulement supprime les appels de méthode, mais aussi toutes les opérations de chaîne qui y entrent.

using UnityEngine;
using System.Collections;

public class ConditionalDebugExample: MonoBehaviour
{
    IEnumerator Start()
    {
        while(true)
        {
            // This message will pop up in Editor but not in builds
            Log("Elapsed: " + Time.timeSinceLevelLoad);
            yield return new WaitForSeconds(1f);
        }
    }

    [System.Diagnostics.Conditional("UNITY_EDITOR")]
    void Log(string Message)
    {
        Debug.Log(Message);
    }
}

Ceci est un exemple simplifié. Vous voudrez peut-être investir du temps dans la conception d'une routine de journalisation à part entière.

Comparaison de chaîne

Ceci est une optimisation mineure, mais cela vaut la peine d'être mentionné. La comparaison des chaînes est légèrement plus complexe qu'on pourrait le penser. Le système essaiera de prendre en compte les différences culturelles par défaut. Vous pouvez choisir d’utiliser une simple comparaison binaire, plus rapide.

// Faster string comparison
if (strA.Equals(strB, System.StringComparison.Ordinal)) {...}
// Compared to
if (strA == strB) {...}

// Less overhead
if (!string.IsNullOrEmpty(strA)) {...}
// Compared to
if (strA == "") {...}

// Faster lookups
Dictionary<string, int> myDic = new Dictionary<string, int>(System.StringComparer.Ordinal);
// Compared to
Dictionary<string, int> myDictionary = new Dictionary<string, int>();

Références du cache

Cacher les références pour éviter les appels coûteux, en particulier dans la fonction de mise à jour. Cela peut être fait en mettant en cache ces références au démarrage si elles sont disponibles ou lorsqu'elles sont disponibles et en recherchant null / bool flat pour éviter d'obtenir à nouveau la référence.

Exemples:

Références du composant de cache

changement

void Update()
{
    var renderer = GetComponent<Renderer>();
    renderer.material.SetColor("_Color", Color.green);
}

à

private Renderer myRenderer;
void Start()
{
    myRenderer = GetComponent<Renderer>();
}

void Update()
{
    myRenderer.material.SetColor("_Color", Color.green);
}

Références d'objet cache

changement

void Update()
{
    var enemy = GameObject.Find("enemy");
    enemy.transform.LookAt(new Vector3(0,0,0));
}

à

private Transform enemy;

void Start()
{
    this.enemy = GameObject.Find("enemy").transform;
}

void Update()
{
    enemy.LookAt(new Vector3(0, 0, 0));
}

De plus, cachez les appels coûteux comme les appels à Mathf dans la mesure du possible.

Évitez d'appeler des méthodes à l'aide de chaînes

Évitez d'appeler des méthodes en utilisant des chaînes pouvant accepter des méthodes. Cette approche utilisera la réflexion qui peut ralentir votre jeu, en particulier lorsqu'il est utilisé dans la fonction de mise à jour.

Exemples:

    //Avoid StartCoroutine with method name
    this.StartCoroutine("SampleCoroutine");

    //Instead use the method directly
    this.StartCoroutine(this.SampleCoroutine());

    //Avoid send message
    var enemy = GameObject.Find("enemy");
    enemy.SendMessage("Die");

    //Instead make direct call
    var enemy = GameObject.Find("enemy") as Enemy;
    enemy.Die();

Éviter les méthodes d'unité vide

Évitez les méthodes d'unité vide. En plus d’être un mauvais style de programmation, les scripts d’exécution impliquent une surcharge minime. Dans de nombreux cas, cela peut augmenter et affecter les performances.

void Update
{
}

void FixedUpdate
{
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow