Übertragungsimplementierung in einem Autospiel

23

Ich versuche ein einfaches Autospiel mit manuellen Gangwechseln zu erstellen. Allerdings habe ich ein bisschen Probleme, die Gangwechsel umzusetzen.

Hier ist mein aktueller Code für das "Auto":

int gear = 1; // Current gear, initially the 1st
int gearCount = 5; // Total no. of gears

int speed = 0; // Speed (km/h), initially 0
int[] maxSpeedsPerGear = new int[]
{
    40,  // First gear max. speed at max. RPM
    70,  // Second gear max. speed at max. RPM
    100, // and so on
    130,
    170
}

int rpm = 0; // Current engine RPM
int maxRPM = 8500; // Max. RPM

public void update(float dt)
{
    if(rpm < maxRPM)
    {
        rpm += 65 / gear; // The higher the gear, the slower the RPM increases
    }

    speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

    if(isKeyPressed(Keys.SPACE))
    {
        if(gear < gearCount)
        {
            gear++; // Change the gear
            rpm -= 3600; // Drop the RPM by a fixed amount
            if(rpm < 1500) rpm = 1500; // Just a silly "lower limit" for RPM
        }
    }
}

Diese Implementierung funktioniert jedoch nicht wirklich. Der erste Gang funktioniert einwandfrei, aber die folgenden Gangwechsel verursachen einen Geschwindigkeitsabfall. Durch das Hinzufügen einiger Debugging-Meldungen erhalte ich beim Ändern des Drehzahlgrenzwerts die folgenden Geschwindigkeitswerte:

Speed at gear 1 before change: 40
Speed after changing from gear 1 to gear 2: 41

Speed at gear 2 before change: 70
Speed after changing from gear 2 to gear 3: 59

Speed at gear 3 before change: 100
Speed after changing from gear 3 to gear 4: 76

Speed at gear 4 before change: 130
Speed after changing from gear 4 to gear 5: 100

Wie Sie sehen, ist die Geschwindigkeit nach jeder Änderung vor der Änderung langsamer. Wie würden Sie die Geschwindigkeit vor dem Gangwechsel berücksichtigen, damit die Geschwindigkeit beim Gangwechsel nicht sinkt?

Manabreak
quelle
1
Ich werde an dieses hervorragende ausführliche Tutorial erinnert: Car Physics for Games . Etwa ein Drittel des Artikels spricht von Motorkraftübertragung.
Eric

Antworten:

17

Berechnen Sie die neue Drehzahl basierend auf dem neuen Gang und der aktuellen Geschwindigkeit des Autos.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

also: statt:

rpm -= 3600; // Drop the RPM by a fixed amount

verwenden:

rpm = max(maxRPM,(float)maxRPM * (float)speed / (float)maxSpeedsPerGear[gear - 1]);

Die Geschwindigkeit ist jetzt vor und nach dem Gangwechsel gleich, und Sie können von dort aus beschleunigen / verzögern.

bearbeiten: hinzugefügt, max(maxRPM, calc)wie Sie es begrenzen möchten. Wie bei einem Auto sollte dies zu einem ziemlich plötzlichen Geschwindigkeitsverlust führen

Baldrickk
quelle
29

Dies liegt daran, dass Ihre Geschwindigkeitsberechnung keine Trägheit aufweist. Sie berechnen es einfach als eine absolute Folge der Motordrehzahl und des Gangs. Wenn Sie jedoch die neue Drehzahl nach dem Hochschalten berechnen, senken Sie sie empirisch in festen Schritten von 3600 U / min.

Das ist dein Fehler. Die Drehzahlabsenkung ist nicht zwischen den Gängen festgelegt. Sie können dies beheben, indem Sie ein zweites Array erstellen, in dem die genaue Anzahl der Drehzahlabfälle zwischen den einzelnen Gängen gespeichert ist.

Die zweite Möglichkeit, dies zu beheben, besteht in der Verwendung physikalisch basierter Berechnungen. Sie führen eine Simulation durch, damit Sie eine numerische Integration durchführen können. Verwenden von Zeit, dtund Euler-Integration oder Verlet-Integration. Das klingt komplex mit Namen und ist es eigentlich gar nicht.

Grundsätzlich würde dies bedeuten, dass Sie eine Nachschlagetabelle für das Motordrehmoment bei bestimmten Drehzahlen erstellen. Dann würden Sie einen Luftwiderstand berücksichtigen, der mit dem Quadrat der Geschwindigkeit zunimmt. Dann würde die Simulation die nächste Geschwindigkeit durch Umkehren des zweiten Newtonschen Gesetzes berechnen f=m a.
Zu finden a=f/m, dann Euler - Integration: speed=speed+a*dt. Das mist ungefähr 1200 (typisches Fahrzeuggewicht). fist die Kraft, die aus dem Motordrehmoment abgeleitet, im Getriebe reduziert und dann mithilfe der Hebelformel unter Berücksichtigung des Radius in Kraft umgewandelt wird. (Ein Vektorkreuzprodukt in der Regel, kann aber durch Multiplikation des Drehmoments mit dem Radius vereinfacht werden, da netwton / meter multipliziert meter = newton.)

Auf diese Weise wird die Motordrehzahl in Abhängigkeit von der linearen Fahrzeuggeschwindigkeit rückwärts berechnet.

v.oddou
quelle
2
Es gibt keine exact number of RPM drop between each gear. Es ist ein Verhältnis, wie @Baldrickk betont. Und während es eine großartige Idee ist, dass die Leistung des Getriebes eher Drehmoment als Geschwindigkeit ist, ist eine Diskussion des Windwiderstands und der Verlet-Integration ein wenig außerhalb des Rahmens der Frage, nein?
Justin
Ja. Für eine präzise Beantwortung der Frage würde ich Baldrickks Antwort empfehlen. Ich habe es positiv bewertet.
v.oddou
5

Zahnräder werden als Untersetzungsmechanismus verwendet.

Bei Verwendung eines vereinfachten Getriebes mit nur zwei Übersetzungsverhältnissen im Getriebe, einem Eingangsgetriebe (Motor) und einem Ausgangsgetriebe (eines der Übersetzungsverhältnisse des Getriebes) haben wir zwei verschiedene Untersetzungsverhältnisse.

Bei einem Eingangszahnrad mit x Zähnen und einem Ausgangszahnrad mit x / 2 Zähnen ist die Drehzahl des Ausgangszahnrads also doppelt so hoch wie die Drehzahl des Eingangszahnrads (Verhältnis von zwei zu eins).

rpm2 = rpm1 * gearRatio

woher:

gearRatio = teeth1 / teeth2

Anstatt jeden Gang durch die fest codierte Geschwindigkeit zu begrenzen, können wir ihn durch die Übersetzung begrenzen. Sie können dann die Drehzahl für ein bestimmtes (rpmEngine, gear) Paar berechnen und, wenn der Gang gewechselt wird, die Motordrehzahl unter Berücksichtigung der bekannten Drehzahl und eines neuen Paares berechnen.

Zur Vereinfachung wird nur ein Motor verwendet, der mit zwei Gängen verbunden ist:

rpmEngine = 5000

gearRatio[1] = 2 #low gear:  one rotation of the engine results in 2 rotations output
gearRatio[2] = 3 #high gear: one rotation of the engine results in 3 rotations output

vehicleSpeed = rpmEngine * gearRatio[selectedGear]

so:

selectedGear = 1
vehicleSpeed = rpmEngine * gearRatio[selectedGear] #5000 * 2 = 10000 

Wenn Sie in den 2. Gang schalten, ist 10000 die Geschwindigkeit. Wenn Sie also die gleiche Formel verwenden, haben Sie jetzt:

vehicleSpeed = 10000 #computed above
selectedGear = 2

so unsere neue rpm:

rpmEngine = vehicleSpeed / gearRatio[selectedGear] #10000 / 3 = 3333.3

Diese 10000 würden dann durch ein Differential (das als nur ein weiterer Gang abstrahiert werden kann, bei Bedarf nachschlagen, leider zwei Glieder nachschauen können) und dann durch die Radgröße zur Berechnung der Fahrgeschwindigkeit in Kilometern oder Meilen pro Stunde weiter reduziert .

Sie würden die Tatsache zu berücksichtigen haben , dass in einen niedrigeren Gang die Motordrehzahl erhöht, so dass ein einfacher Ansatz besteht darin zu prüfen , MaxRPM und begrenzt die Drehzahl nach der Verschiebung auf Ihre maximale Drehzahl und damit die Fahrzeuggeschwindigkeit verringert wird .

Im Grunde genommen berechnen Sie jedes Mal, wenn ein Gangwechsel auftritt, die Motordrehzahl aus der Fahrzeuggeschwindigkeit, begrenzen sie durch die max.

Für eine realistische Simulation müssen Sie mindestens das Motordrehmoment (Antwort von v.oddou) und den Kupplungsschlupf berücksichtigen, was zusammen folgende Auswirkungen hätte: - Beim Hochschalten wird vorausgesetzt, dass der Schaltvorgang schnell genug ist, damit die Motordrehzahl nicht sinkt Die Drehzahl wird erhöht, während die Motordrehzahl gesenkt wird, bis sie ausgeglichen ist. Beim Herunterschalten wird die Fahrzeuggeschwindigkeit gesenkt, bis der Motor auf die neue Drehzahl angehoben wird. Dies geht jedoch wahrscheinlich über die "einfache" Implementierung hinaus.

cristiancrc
quelle
4

Denken Sie daran, dass ein eingelegtes Schaltgetriebe ein Zwei-Wege-Gerät ist. Der Motor kann das Fahrzeug beschleunigen, genauso wie das Fahrzeug (genauer gesagt sein Impuls) den Motor beschleunigen kann.

Dies war ein echtes Problem bei frühen Schaltgetrieben. Das Herunterschalten würde den Motor plötzlich auf eine höhere Drehzahl bringen, die Zündzyklen aus dem Takt bringen und möglicherweise zum Abwürgen des Motors führen. Dies wurde durch fachmännisches Fahren ausgeglichen, bei dem der Fahrer den Motor auf die richtige Drehzahl bringen musste, bevor die Kupplung gelöst wurde, um das Getriebe einzurücken.

Das war, bis die Synchronisation entwickelt wurde. Es ist ein Mechanismus, der das Einrücken des Getriebes verhindert, bis die Eingangs- und Ausgangsdrehzahlen synchron sind.

Was ich also vorschlage, ist, dass Sie die Synchronisierung emulieren und das Getriebe nicht einlegen, bis die Motordrehzahl und die Autodrehzahl auf dem aktuellen Niveau übereinstimmen.

Kantenläufer
quelle
2

Die bestehende Antwort scheint viel zu komplex. Bei einem Spiel ist RPM nur eine Anzeige auf dem Bildschirm. Die tatsächliche Geschwindigkeit ist die tatsächliche Variable. Das Übersetzungsverhältnis bestimmt, wie Sie die Motordrehzahl in U / min umwandeln. Das Schalten ändert das Übersetzungsverhältnis, aber nicht die Geschwindigkeit. Offensichtlich ändert sich die Drehzahl auch als Umkehrung des Übersetzungsverhältnisses.

Überdrehen (Herunterschalten über die 8500 U / min-Grenze hinaus) ist etwas, das Sie separat implementieren würden, aber es ist eine schlechte Sache in Autos und Sie können zulassen, dass es eine schlechte Sache in Ihrem Spiel ist.

MSalters
quelle
2
Die existierende Antwort ist genau das, was die meisten Spiele, die ich gesehen habe, tun, sogar einfache Arcade-Spiele, weil es wirklich nicht so komplex ist. RPM auf dem Bildschirm kann nur eine Zahl sein, aber dieser Ansatz gibt Ihnen sowohl die Zahl (die Sie für visuelle Indikatoren sowieso zwicken können), als auch das Verhalten, um diese Zahlen zu entsprechen
Selali Adobor
2

Wie bereits erwähnt, sollte die Fahrzeuggeschwindigkeit der tatsächliche Wert sein und daraus die Drehzahl abgeleitet werden. Das Hochschalten sollte dazu führen, dass die Motordrehzahl abnimmt, da sich das Verhältnis von U / min pro km / h "sofort" ändert, die Fahrzeuggeschwindigkeit jedoch nicht.

Ich würde jedoch vorschlagen, dass sich das Motordrehmoment mit der Drehzahl bis zu einem bestimmten Grenzwert erhöht und darüber hinaus fällt. Die Geschwindigkeit, mit der ein Fahrzeug beschleunigt, sollte proportional zum Drehmoment geteilt durch das Übersetzungsverhältnis minus dem Luftwiderstand sein, der proportional zum Quadrat der Geschwindigkeit ist. Wenn aufeinanderfolgende Gänge ein Übersetzungsverhältnis von 1: 41: 1 haben, erfolgt ein optimales Schalten für die Beschleunigung an dem Punkt, an dem das Drehmoment im unteren Gang auf etwa 70% des Drehmoments im nächsthöheren Gang gefallen ist.

Superkatze
quelle
2

Aufbauend auf @ v.oddou mit

max(maxRPM, calc)

Dies würde dazu führen, dass die Drehzahl beim Schalten der Gänge sofort maximal wird und kein reibungsloser Übergang von Gang zu Gang möglich ist. Der richtige Weg wäre, nach Drehzahlen zu suchen, indem man die Geschwindigkeitsvariable als Gleichung verwendet.

speed = (int) ((float)rpm / (float)maxRPM) * (float)maxSpeedsPerGear[gear - 1]);

Löse nach U / min

rpm = (maxRPM * speed) / maxSpeedsPerGear[gear - 1] ;

Da der Gang 1 höher ist als zuvor, sind die Drehzahlen niedriger.

Weiße Entwicklungsstudios
quelle