Ho il seguente scenario per il quale ho riscontrato problemi di prestazioni:
Il contesto è un editor di livelli di un nuovo motore per un vecchio videogioco (la cui origine non è disponibile) in Unity . Fondamentalmente sto scrivendo un editor di livelli per Unity per modellare le vecchie strutture dati in quelle contemporanee, più utilizzabili, cioè parti / entità invece di un mucchio di modelli / poligoni non collegati.
Ecco un albero di come sono organizzate le cose nel vecchio gioco:
- Container (dozzine)
- Modelli (centinaia)
- Poligoni (migliaia)
- Modelli (centinaia)
Ecco cosa mi piacerebbe realizzare:
- Gruppo / i: per raggruppare oggetti correlati
- Oggetto / i: un albero, una nave ecc ...
- Parte / i: parti di un oggetto con materiale specifico ecc ...
- Oggetto / i: un albero, una nave ecc ...
A seconda di come appare l'oggetto finale sullo schermo, i dati iniziali (modelli / poligoni) sono un disastro, dove ci sono parti unite o non correlate in un modello e nei suoi poligoni.
Altri problemi emergono a causa di ciò, ad esempio, quello che era un semplice aggiornamento puntatore per aggiornare una texture o un colore non è semplicemente possibile all'interno di Unity.
Qui ho bisogno di cose e cosa ho fatto:
Devo essere in grado di tracciare riferimenti impliciti ed espliciti a modelli e poligoni. Questo per garantire che vengano creati oggetti validi e quindi prevenire contenuti non corretti.
Fondamentalmente l'utente può creare una parte dal modello o uno dei suoi poligoni, a differenza di ciò che è stato scelto prima.
Ecco un'immagine con spiegazioni:
-
Scene9 è di tipo
Container
-
M123_456_ABC ... sono di tipo
Model
-
P123_456_ABC ... sono di tipo
Polygon
- Un'icona verde è un riferimento esplicito
- Un'icona gialla è un riferimento implicito
- Un'icona rossa è un elemento senza riferimenti
Inoltre,l'interfacciautenteèaumentatadaglielementichevengonodisabilitatiognivoltachesonoappropriatiperaiutarel'utenteascegliereleazionigiustepercostruireillivello,ecc...
Qui,iproblemichestoriscontrando:
Laricercadiriferimentiespliciti/implicititracirca300modellie7000poligonidiventalentaneltempomanmanochelerelazionivengonocreate.
HoutilizzatounpaiodiList<T>
efaccioqueryLINQtraloro:
- tutto
- tuttiimodelli
- tuttiipoligoni
- modelliimpliciti
- poligoniimpliciti
- modelliespliciti
- poligoniespliciti
Menolalogicadeglispaghetti,funzionamaèlenta.Poihoeseguitol'upgradeaHashSet<T>
conComparer<T>
personalizzatochehanotevolmentemiglioratolavelocità,manonèancoraabbastanzaveloce.Tuttociòsibloccanell'interfacciautente.
Laconsiderazioneprincipaleècheall'internodiUnityiloopsonopiuttostostretti,le
Sto iniziando a considerare che il mio approccio con le liste è errato e pensavo che una migliore struttura dei dati potesse essere utilizzata per query performanti.
Puoi suggerire una struttura dati più appropriata da utilizzare per tale scenario?
Modifica
Questo è un diagramma che mostra l'approccio nuovo che sto cercando dopo i tuoi suggerimenti:
Note:
-
IScenePrimitive
è composto da 3% diint
eEnum
-
ISceneReference.IsRef
è semplicementeIsRefExplicit || IsRefImplicit
- Le cose mancanti qui sono un dizionario in
Scene
per l'accesso rapido a un modello / poligono, quando l'utente seleziona qualcosa recupero questi usando gli hash senza dover enumerare, ecc ...
Parti interessanti nel codice:
SceneModel:
public override bool IsRefExplicit
{
get { return _isRefExplicit; }
set
{
_isRefExplicit = value;
if (value)
{
Debug.Assert(_polygons.None(s => s.IsRefExplicit));
foreach (var polygon in _polygons)
polygon.IsRefImplicit = true;
}
else
{
Debug.Assert(_polygons.All(s => s.IsRefImplicit));
foreach (var polygon in _polygons)
polygon.IsRefImplicit = false;
}
}
}
public override bool IsRefImplicit
{
get { return _isRefImplicit; }
set
{
_isRefImplicit = value;
if (value)
Debug.Assert(_polygons.Any(s => s.IsRefExplicit));
}
}
ScenePolygon:
public override bool IsRefExplicit
{
get { return _isRefExplicit; }
set
{
_isRefExplicit = value;
if (value)
{
Debug.Assert(!Model.IsRefExplicit);
Model.IsRefImplicit = true;
}
else
{
Debug.Assert(Model.IsRefImplicit);
Model.IsRefImplicit = false;
}
}
}
public override bool IsRefImplicit
{
get { return _isRefImplicit; }
set
{
_isRefImplicit = value;
Debug.Assert(Model.IsRefExplicit);
}
}
Questo è tutto ciò che accade realmente, LINQ su una dozzina di elementi invece di molti altri (300 modelli che interrogano ogni 7000 poligoni X). Devo ancora provarlo per vedere come funziona, ma dovrebbe eseguire molto più velocemente, per continuare.