Die neueste Kollisionsereignisverarbeitung der Unity DOTS Physics-Physik-Engine

Kürzlich hat DOTS eine offizielle Version veröffentlicht und eine leistungsstarke Physik-Engine basierend auf dem DOTS-Konzept implementiert. Heute werden wir die Kollisionsereignisverarbeitung und die Kernkonzepte dieser Physik-Engine mit Ihnen teilen und vorstellen.

Die Hauptprozesse und Pipeline der Unity.Physics-Physik-Engine

Die Unity.Physics-Physik-Engine führt Simulations-Iterationsberechnungen hauptsächlich durch die folgenden Schritte durch:

Schritt 1: Erhalten Sie die Statusdaten unseres aktuellen Objekts von der ECS-Komponente in der Entität.

Schritt 2: Führen Sie eine grobe Breitphasenberechnungsphase durch, durchqueren Sie alle Körper in der physischen Welt und bestimmen Sie mithilfe der AABB-Umfangsberechnung schnell, welche Objekte sich schneiden können. Bei der groben Berechnung werden diejenigen ausgeschlossen, die sich nicht schneiden, und diejenigen, die sich nicht schneiden, werden nicht geändert Bewegungszustand;

Schritt 3: Narrowphase-Stufe: Führen Sie weitere präzise Berechnungen für Objekte durch, die sich überschneiden können. Berechnen Sie genaue Kollisionspunkte und zugehörige Kollisionsinformationen basierend auf ihren physikalischen Formen.

Schritt 4: Basierend auf diesen Kollisionsinformationen berechnet unsere Physik-Engine spezifische Kollisionsinformationen, Gelenke, Reibungskräfte, Widerstände usw., kombiniert mit den Prinzipien der Physik, um die Geschwindigkeit, Winkelgeschwindigkeit und andere Bewegungszustände unseres physischen starren Körpers zu berechnen .

Schritt 5: Berechnen Sie basierend auf dem neuen Bewegungszustand iterativ alle sich vorwärts bewegenden Objekte (Lineargeschwindigkeit, Winkelgeschwindigkeit, Reibung usw.), um die Position und andere Informationen des neuen starren Körpers in diesem Rahmen zu berechnen.

Schritt 6: Unity Physic synchronisiert die Position und Geschwindigkeit des physischen starren Körpers mit der LocalTransform-Komponente und der PhysicVelocity-Komponente der Knoten-Entität über das ExportPhysicsWorld-System, sodass sich die gerenderte Entität synchron mit dem starren Körper der Physik-Engine bewegt.

Rechts! Hier gibt es eine Spieleentwicklungs-Austauschgruppe , in der sich eine Gruppe von Anfängern versammelt, die gerne Spiele lernen, sowie einige technische Experten, die sich mit der Spieleentwicklung beschäftigen. Sie sind herzlich eingeladen, vorbeizukommen, sich auszutauschen und zu lernen.

In DOTS wird die Iterationsreihenfolge in DOTS basierend auf den System- und SystemGroup-Baumzeilenstrukturen bestimmt. Dies ist ein sehr wichtiges Konzept in DOTS. Unity Physics stützte die oben genannten Schritte und die Logik auf die ECS-Designidee und entwarf das entsprechende System bzw. die Systemgruppe. Die Struktur ist wie folgt:

->FixedStepSimulationSystemGroup:

->PhysicsSystemGroup

->PhysicsInitializeGroup(Systemgruppe)

->PhysicsSimulationGroup(SystemGroup)

->PhysicsCreateBodyPairsGroup

->PhysikCreateContactsGroup

->PhysikCreateJacobiansGroup

->PhysicsSolveAndIntegrateGroup

->System: ExportPhysicsWorld

Die iterativen Berechnungen aller Physik-Engines basieren auf der FixedStepSimulationSystemGroup, die physikalische Simulationen in festen Zeitintervallen iteriert, um die Konsistenz und Stabilität der Physik-Engine aufrechtzuerhalten. Alle Simulationsberechnungen der Physik-Engine werden unter der PysicsSystemGroup abgelegt. PysicsSystemGroup enthält PhysicsInitializeGroup, PhysicsSimulationGroup und ein ExportPhysicsWorld-System. Der oben erwähnte Schritt 1 wird in der PhysicsInitializeGroup-Phase abgeschlossen, die Schritte 2 bis 5 werden in der PhysicsSimulationGroup abgeschlossen. Nachdem die PhysicsSimulationGroup abgeschlossen ist, ist die iterative Berechnung eines Frames der Physik-Engine abgeschlossen. Schließlich sind die internen Daten der Physik-Engine abgeschlossen über das System von ExportPhysicsWorld mit der PhysicsVelocity der Entität synchronisiert. ECS-Komponenten wie LocalTransform. In PhysicsSimulationGroup gibt es vier weitere Untergruppen, die den Ausführungsschritten von Schritt 2 bis Schritt 5 entsprechen.

Behandlung von Kollisionserkennungsereignissen in Unity Physics

Wenn die Gruppenausführung von PhysicsSimulationGroup abgeschlossen ist, sind die Simulation und die iterative Berechnung der gesamten Physik-Engine abgeschlossen. Während des Simulationsprozesses wird eine PhysicsWorld generiert. Alle starren Körper und andere verwandte physikalische Daten (Position, Geschwindigkeit usw.) in der physischen Welt können über PhysicsWorld abgerufen und schließlich in die ECS-Komponente von Entity exportiert werden. Alle Ereignisse in der physikalischen Simulation werden im Simulationsobjekt gespeichert. Zu diesen Ereignissen gehören unsere allgemeinen Kollisionsereignisse und Triggerereignisse. Im herkömmlichen Modus verarbeiten wir diese Ereignisse über Rückruffunktionen. Im DOTS-Modus verarbeiten wir diese Ereignisse einheitlich innerhalb einer Systemverknüpfung. Der Verarbeitungsablauf für Kollisionen und Auslöseereignisse der Physik-Engine ist wie folgt:

Schritt 1: Schreiben Sie eine Systemverarbeitungslogik zur Verarbeitung physischer Ereignisse.

Schritt 2: Geben Sie den Zeitpunkt der Systemausführung an, der vor oder nach PhysicsSimulationGroup liegen muss, damit die Daten des Kollisionsereignisses abgerufen werden können.

Schritt 3: Durch das Schreiben eines Jobs werden alle aktuell auftretenden Kollisionsereignisse durchlaufen und dann die Verarbeitungslogik für jedes Kollisionsereignis geschrieben.

Schritt 4: Rufen Sie den Simulations-Singleton ab, der das Ereignis speichert, und übergeben Sie ihn zur spezifischen Ausführung an den Job.

Umgang mit Kollisionsereignissen:

Wenn alle iterativen Simulationsberechnungen abgeschlossen sind, werden alle Kollisionsereignispaare im Prozess im Simulationsobjekt gespeichert. Wir können das Simulationsobjekt über (SystemBase|SystemAPI|EntityQuery).GetSingleton<SimulationSingleton>().AsSimulation() abrufen.

Um alle Kollisionsereignisse zu verarbeiten, schreiben wir zunächst ein System zum Schreiben der Ereignisverarbeitungslogik und dann einen Job, der von IcollisionEventsJob erbt, sodass alle Kollisionsereignisse im Job durchlaufen werden können und jedes Kollisionsereignis die Execute-Funktion des Jobs aufruft. Behandeln Sie die Logik jedes darin enthaltenen Kollisionsereignisses. Code wie folgt anzeigen:

[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateBefore(typeof(PhysicsSimulationGroup))] // We are updating before `PhysicsSimulationGroup` - this means that we will get the events of the previous frame
public partial struct GetNumCollisionEventsSystem : ISystem
{
    [BurstCompile]
 public partial struct CountNumCollisionEvents : ICollisionEventsJob
    {
 public NativeReference<int> NumCollisionEvents;
 public void Execute(CollisionEvent collisionEvent)
        {
            NumCollisionEvents.Value++;
        }
    }
    [BurstCompile]
 public void OnUpdate(ref SystemState state)
    {
        NativeReference<int> numCollisionEvents = new NativeReference<int>(0, Allocator.TempJob);
        state.Dependency = new CountNumCollisionEvents
        {
            NumCollisionEvents = numCollisionEvents
        }.Schedule(SystemAPI.GetSingleton<SimulationSingleton>());
 // ...
    }
}

Triggerereignis-TriggerEvent-Behandlung:

Triggerereignisse ähneln Kollisionsereignissen. Wir müssen nur einen ItriggerEventsJob schreiben, um alle aktuellen Triggerereignisse zu durchlaufen. Der Code lautet wie folgt:

[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]
[UpdateAfter(typeof(PhysicsSimulationGroup))] // We are updating after `PhysicsSimulationGroup` - this means that we will get the events of the current frame.
public partial struct GetNumTriggerEventsSystem : ISystem
{
    [BurstCompile]
 public partial struct CountNumTriggerEvents : ITriggerEventsJob
    {
 public NativeReference<int> NumTriggerEvents;
 public void Execute(TriggerEvent collisionEvent)
        {
            NumTriggerEvents.Value++;
        }
    }
    [BurstCompile]
 public void OnUpdate(ref SystemState state)
    {
        NativeReference<int> numTriggerEvents = new NativeReference<int>(0, Allocator.TempJob);
        state.Dependency = new CountNumTriggerEvents
        {
            NumTriggerEvents = numTriggerEvents
        }.Schedule(SystemAPI.GetSingleton<SimulationSingleton>());
 // ...
    }
}

Das ist alles für den heutigen Austausch. Studenten, die die vollständigen Projekttools und den Quellcode dieses Artikels benötigen, können uns folgen.

Das Video-Tutorial ist wie folgt

Unity: DOTS Zone​www.bycwedu.com/promotion_channels/1830504531​Bearbeiten

Guess you like

Origin blog.csdn.net/voidinit/article/details/135153495