Der letzte Pin

Du bist der letzte verbleibende Stift! Neige deinen Kopf, um den herannahenden Bowlingkugeln auszuweichen.

thelastpin

Gestalten Sie es mit dem Beispielprojekt ganz nach Ihren Wünschen.

globalscorecontroller

Studio: GLOBAL SCORE CONTROLLER checkmark bullet

Ein Beispielprojekt, das Ihnen helfen soll, globale Ereignisse zu verstehen und insbesondere, wie sie zur Aktualisierung einer Bewertung verwendet werden können.

Beispielprojekt ansehen

Behind the Build: The Last Pin

Written by Sam Guilmard

May 5, 2025


Introduction

Dieses Projekt wurde ins Leben gerufen, um ein besseres Verständnis für die Entwicklung von Spielen in Niantic Studio zu vermitteln, bei denen der Nutzer physische Eingaben vornehmen muss, um die Kernmechanik des Spiels zu steuern. In diesem Beispiel wird die Kopfdrehung des Benutzers verwendet, um den Hauptspieler zu steuern. Es nutzt außerdem die integrierte Animationskomponente, um viele Elemente im Spiel zu steuern, beispielsweise die Bewegungen der Gegner. 


Das Spiel heißt "THE LAST PIN" und du spielst einen Bowlingpin, der den herannahenden Bowlingkugeln ausweichen muss. Je länger du überlebst, desto mehr Punkte bekommst du. Sobald der Spieler von einer Bowlingkugel getroffen wird, ist das Spiel vorbei. Im Laufe des Spiels erhöht sich die Geschwindigkeit, mit der Bowlingkugeln erscheinen, ebenso wie die Geschwindigkeit der Kugeln.

Project Structure

3D-Szene-
  • Die Gesamtszene ist relativ einfach und verwendet eine Mischung aus 3D-Modellen und primitiven Formen, um die Umgebung zu erstellen. Es verwendet außerdem 3D-UI-Elemente, sodass deren Position im 3D-Raum verändert werden kann.
Assets
  • Dieses Projekt enthält 2 3D-Assets. Die Rinne wird in der Szene auf beiden Seiten der Bowlingbahn platziert, und der Pin wird vom Benutzer durch Drehen des Kopfes gesteuert. Sie können sich den Pin und den Hauptspieler vorstellen. 
  • Es gibt 1 Audiodatei, die abgespielt wird, wenn der Pin vom Ball getroffen wird. 
  • Im Texturordner befindet sich eine Kombination aus Modelltexturen und UI-Elementen.
  • Außerdem gibt es insgesamt 10 verschiedene Balltexturen. Diese werden zufällig auf jeden Ball angewendet, sobald er erscheint.
    Skripte
    für "
"
  • In diesem Projekt gibt es nur ein Skript namens "GameController", das die gesamte für das Spiel erforderliche Logik verarbeitet.

Implementation

In diesem Abschnitt der Dokumentation werden einige der grundlegenden Mechaniken des Spiels erläutert.

- Spielerbewegungs- 
Innerhalb des Schemas wird auf das Objekt "Pin" verwiesen, mit dem Sie Komponenten des Objekts wie Position, Drehung, Skalierung, Material usw.

         
schema: { 
// Add data that can be configured on the component. 
pin: ecs.eid, 
}, 

      

In der Szenenhierarchie wählen wir nun die Komponente "Game Controller" (an die das Skript "GameController" angehängt ist) aus und navigieren im Inspektor-Panel zum Skript. Es gibt eine Option für "Pin", also stellen Sie sicher, dass Sie das richtige Objekt über das Dropdown-Menü auswählen.

Nun können wir in der Add-Funktion des "GameController"-Skripts eine Referenz zu diesem Objekt erstellen, damit wir in anderen Funktionen leicht darauf verweisen können. 

         
const { 
pin, 
} = component.s

      

Ebenfalls in der Add-Funktion erstellen wir zwei Ereignis-Listener. Der eine hört darauf, wann das Gesicht angezeigt wird ("facecontroller.faceupdated"), der andere darauf, wann das Gesicht ausgeblendet wird ("facecontroller.facelost"). Am Ende des Ereignis-Listeners definieren wir den Namen der Funktion, die aufgerufen werden soll, wenn dieses Ereignis eintritt – wenn das Gesicht aktualisiert wird, wird die Funktion "show" aufgerufen, und wenn das Gesicht verloren geht, wird die Funktion "lost" aufgerufen. 

         
// listener for head rotation and pin movement 
world.events.addListener(world.events.globalId, 'facecontroller.faceupdated', show) 
// listener for losing head rotation 
world.events.addListener(world.events.globalId, 'facecontroller.facelost', lost) 

      

Die Funktion "show" übergibt die Werte für die Kopfposition und -drehung des Benutzers. Innerhalb dieser Funktion wird eine Variable "xRot" erstellt, der der Wert der X-Drehung des Kopfes des Benutzers zugewiesen wird. Innerhalb einer IF-Anweisung, die überprüft, ob das Spiel gerade läuft, wird der Wert "xRot" ständig auf die Position der Pins X innerhalb der Szene angewendet. Dieser Wert wird mit einer weiteren Variablen "pinSpeed" multipliziert, die im GameController-Szenenobjekt leicht bearbeitet werden kann, da es sich um eine weitere Schemavariable handelt. 

         
// controls the movement of the pin 
const show = ({data}) => { 
const xRot = data.transform.rotation.x 
// console.log(xRot) 
if (playing == true) { 
ecs.Position.set(world, pin, {x: Math.min(Math.max(xRot * -pinSpeed, -1.5), 1.5), y: 0, z: 8}) 
} 
} 

      

Pin-Geschwindigkeits-

Je höher dieser Wert, desto "schneller" bewegt sich der Pin. Der Grund dafür, dass dieser Wert negiert wird, ist, dass er sich in Bezug auf die Szene und die Position des Benutzers in die richtige Richtung bewegt. Sie können auch sehen, dass dieser Wert, wenn er auf das Pin-Objekt angewendet wird, ebenfalls in eine Math.min- und Math.max-Funktion eingebettet ist. Dies dient dazu, die Position der Pins auf dem Bildschirm zu begrenzen, sodass sie innerhalb der Spielgrenzen bleiben müssen und nicht betrogen werden kann. 
Mit der Funktion "Verloren" wird die Position des Pins auf die ursprüngliche Startposition zurückgesetzt, damit der Spieler nicht schummeln kann, indem er sein Gesicht versteckt.


- Ball-Spawning 
Wenn das Spiel beginnt (der Benutzer tippt auf den Bildschirm), werden die Bälle gespawnt – jeder Ball hat eine zufällige X-Startposition und eine zufällige X-Endposition, damit sich die Bälle diagonal bewegen und das Spiel schwieriger wird. Jeder Ball wird mit einer zunehmenden, jedoch zufälligen Geschwindigkeit befördert, wobei je nach Entfernung zwischen der Start- und Endposition X eine gewisse Rotation und eine zufällige Textur (aus 10 Optionen) auf jeden Ball angewendet wird. Die meisten dieser Funktionen werden durch die Implementierung des in Niantic Studio integrierten Animationscontrollers ausgeführt. 
Ähnlich wie bei der Erstellung einer Objektreferenz für den Pin müssen wir erneut 10 verschiedene Objektreferenzen innerhalb des Schemas für alle 10 Bowlingkugeln erstellen. 

         
schema: { 
// Add data that can be configured on the component. 
ball1: ecs.eid, 
ball2: ecs.eid, 
ball3: ecs.eid, 
ball4: ecs.eid, 
ball5: ecs.eid, 
ball6: ecs.eid, 
ball7: ecs.eid, 
ball8: ecs.eid, 
ball9: ecs.eid, 
ball10: ecs.eid, 
pin: ecs.eid, 
}, 

      

Wir können nun wieder die Dropdown-Auswahlleiste im GameController-Skript verwenden, das dem GameController-Objekt in der Szene zugeordnet ist, um jeden Ball anzuwenden.

In der Funktion "Add" können wir eine Referenz zu jedem Ball erstellen, sodass er im gesamten Skript leicht zugänglich ist. 

         
add: (world, component) => { 
// Runs when the component is added to the world. 
const { 
ball1, 
ball2, 
ball3, 
ball4, 
ball5, 
ball6, 
ball7, 
ball8, 
ball9, 
ball10, 
pin, 
} = component.schema 

      

Wenn das Spiel startet, entweder zu Beginn der Erfahrung oder wenn es neu gestartet wird, wird die Funktion "spawnBall" aufgerufen. 

 

         
function spawnBall() { 
// checks if the game is currently playing 
if (playing == true) { 
// decrease the spawn time every time a ball is spawned 
if (spawnTime > spawnFrequencyMinimum) { 
spawnTime -= spawnFrequencyMultiplier 
} 
const randomxStart = getRandomStartX() 
const randomxEnd = getRandomEndX() 
// this calculates the difference between the x start position and x end position - the higher the difference the more rotation that is added const differenceInDistance = Math.abs(randomxStart - randomxEnd) 
// if the x start position is bigger than the end then the ball is moving left 
if (randomxStart >= randomxEnd) { 
curveLeft = true 
} else { 
curveLeft = false 
}
updateMaterial() 
applyScaleAnimation() 
world.setPosition(balls[currentBall], randomxStart, 0.375, -0.5) applyPositionAnimation(randomxStart, randomxEnd) 
applyRotationAnimation(differenceInDistance) 
// Increase current ball or reset 
if (currentBall == 9) { 
currentBall = 0 
} else { 
currentBall++ 
} 
// time out function to delay the next spawning of a ball 
world.time.setTimeout(() => { 
if (playing == true) { 
spawnBall() 
} 
}, spawnTime) 
} 
} 

      

Alles innerhalb der Funktion "spawnBall" ist in einer if-Anweisung verschachtelt, die überprüft, ob das Spiel gerade gespielt wird. Dadurch wird sichergestellt, dass nach Spielende keine weiteren Bälle mehr generiert werden. 
Am Ende der Funktion wird die Funktion "setTimeout" verwendet, um die Funktion "spawnBall" erneut aufzurufen. Der Wert "spawnTime" ist die Zeit, die vergehen muss, bevor die Funktion aufgerufen wird. Dieser Wert wird bei jedem Aufruf der Funktion zu Beginn der Funktion geändert. 

         
if (spawnTime > spawnFrequencyMinimum) { 
spawnTime -= spawnFrequencyMultiplier 
} 

      

Es wird zunächst geprüft, ob die aktuelle spawnTime größer ist als die spawnFrequencyMinimum. Wenn ja, subtrahiere den spawnFrequencyMultiplier von der spawnTime, wenn nicht, dann mache nichts. Wir begrenzen diesen Wert, damit nicht zu viele Bälle gleichzeitig auf dem Bildschirm zu sehen sind, was das Spiel unspielbar machen und die Bildrate drastisch beeinträchtigen würde.

Als Nächstes weisen wir die X-Startposition und die X-Endposition zu, indem wir diese beiden Funktionen aufrufen. 

         
const randomxStart = getRandomStartX() 
const randomxEnd = getRandomEndX() 

      

Beide Funktionen funktionieren auf dieselbe Weise und beginnen mit der Definition des Werts "negativeStart" mit einem Zufallswert von entweder 0 oder 1. Dies wird verwendet, um zu bestimmen, ob die X-Position negativ oder positiv ist. Dann wird dem "xValue" ein zufälliger Wert zwischen 0 und 2 zugewiesen. Dieser Wert wird dann zurückgegeben, aber wenn "negativeStart" gleich 0 ist, wird der x-Wert negiert. 

         
// Get a random x value for ball start position 
function getRandomStartX() { 
const negativeStart = Math.floor(Math.random() * (2)) 
const xValue = Math.random() * (2) 
if (negativeStart == 0) { 
return xValue * -1 
} else { 
return xValue 
} 
} 

      

Als Nächstes wird "differenceInDistance" anhand der beiden neuen x-Positionen ein Wert zugewiesen, um zu berechnen, wie weit sie auf der X-Achse voneinander entfernt sind. Dies wird verwendet, wenn die Drehung später angewendet wird.

         
const differenceInDistance = Math.abs(randomxStart - randomxEnd) 

      

Anschließend berechnen wir, in welche Richtung sich der Ball bewegt: Bewegt sich der Ball diagonal nach links oder nach rechts? Wir verwenden dies erneut, um die Rotationsanimation anzuwenden. Wenn sich der Ball nach links bewegt, sollte er sich auch nach links drehen.

         
// if the x start position is bigger than the end then the ball is moving left 
if (randomxStart >= randomxEnd) { 
curveLeft = true 
} else { 
curveLeft = false 
}

      

Die nächste aufgerufene Funktion ist die Funktion "applyMaterial". Zu Beginn der Add-Funktion wurde ein Array für Texturnamen erstellt. Ein weiteres Array wird definiert, das alle Bälle enthält.

         
const textures = ['ballTexture1', 'ballTexture2', 'ballTexture3', 'ballTexture4', 'ballTexture5', 'ballTexture6', 'ballTexture7', 'ballTexture8', 'ballTexture9', 'ballTexture10'] 
const balls = [ball1, ball2, ball3, ball4, ball5, ball6, ball7, ball8, ball9, ball10] 

      

Es ist wichtig, dass diese Namen mit den Texturen in Ihrem Asset-Ordner übereinstimmen, jedoch keine Dateiendung enthalten, z. B. png. 
Zu Beginn der Funktion "applyMaterial" wird eine Zufallszahl zwischen 0 und 9 generiert.

         
currentTexture = Math.floor(Math.random() * 10) 
// Apply the texture to the object 
ecs.Material.set(world, balls[currentBall], { 
textureSrc: `${require(`./assets/${textures[currentTexture]}.png`)}`, roughness: 0.5, 
metalness: 0.5, 
}) 

      

Es ist wichtig, dass diese Namen mit den Texturen in Ihrem Asset-Ordner übereinstimmen, jedoch keine Dateiendung enthalten, z. B. png. 
Zu Beginn der Funktion "applyMaterial" wird eine Zufallszahl zwischen 0 und 9 generiert.

         
currentTexture = Math.floor(Math.random() * 10) 
// Apply the texture to the object 
ecs.Material.set(world, balls[currentBall], { 
textureSrc: `${require(`./assets/${textures[currentTexture]}.png`)}`, roughness: 0.5, 
metalness: 0.5, 
}) 

      

Als Nächstes wird "applyScaleAnimation" aufgerufen – dies ist eine einfache Funktion, mit der die Kugeln beim Erscheinen auf dem Bildschirm skaliert werden, damit sie nicht einfach "auftauchen". 

         
function applyScaleAnimation() { 
ecs.ScaleAnimation.set(world, balls[currentBall], { 
autoFrom: false, 
fromX: 0, 
fromY: 0, 
fromZ: 0, 
toX: 1, 
toY: 1, 
toZ: 1, 
duration: 500, 
loop: false, 
easeIn: false, 
}) 
}

      

Als Nächstes wird "applyScaleAnimation" aufgerufen – dies ist eine einfache Funktion, mit der die Kugeln beim Erscheinen auf dem Bildschirm skaliert werden, damit sie nicht einfach "aus dem Nichts" auftauchen. 

         
world.setPosition(balls[currentBall], randomxStart, 0.375, -0.5) 

      

Anschließend wird die Funktion "applyPositionAnimation" aufgerufen, um die Bewegung des Bowlingballs hinzuzufügen. Die Werte "randomxStart" und "randomxEnd" werden an diese Funktion übergeben. Dies ist ein Paradebeispiel dafür, wie das integrierte Animationssystem von Niantic Studio funktioniert. Der Vorteil der Verwendung des Animationssystems gegenüber einem Physiksystem, das Kräfte anwendet, besteht darin, dass Sie die Geschwindigkeit besser kontrollieren können und diese beispielsweise nicht von der Qualität des Geräts abhängt. 

         
applyPositionAnimation(randomxStart, randomxEnd) 
// Apply the position animation to the new ball 
function applyPositionAnimation(xStart, xEnd) { 
ecs.PositionAnimation.set(world, balls[currentBall], { 
autoFrom: false, 
fromX: xStart, 
fromY: 0.375, 
fromZ: -0.5, 
toX: xEnd, 
toY: 0.375, 
toZ: 10, 
duration: getRandomSpeed(), 
loop: false, 
easeIn: true, 
}) 
} 

      

Wie Sie sehen können, wird die "Dauer" dieser Animation durch den Aufruf der Funktion "getRandomSpeed" definiert. Die Dauer wird in Millisekunden angegeben. Je niedriger dieser Wert ist, desto schneller wird die Animation. 


Die Funktion "getRandomSpeed" generiert eine Zufallszahl zwischen 0 und dem Wert "ballSpeedVariation", der standardmäßig auf 200 gesetzt ist. Dieser Wert wird dann zur Variablen "initialSpeed" addiert, die auf 3000 gesetzt ist. Das bedeutet, dass die Dauer der Animation zwischen 3000 und 3200 Millisekunden liegen kann (mit geringfügigen Abweichungen). Jedes Mal, wenn diese Funktion aufgerufen wird, wird überprüft, ob "initialSpeed" größer als "maximumBallSpeed" ist.

         
function getRandomSpeed() { 
newSpeed = (Math.random() * ballSpeedVariation) + initialSpeed 
if (initialSpeed > maximumBallSpeed) { 
initialSpeed -= ballSpeedIncreaseValue 
} 
return newSpeed 
} 

      

Anschließend wird die Funktion "applyRotationAnimation" aufgerufen und der Wert "differenceInDistance" an diese Funktion übergeben. Hier wird auch die Variable "curveLeft" verwendet. Die Rotationsanimation, die auf den Ball angewendet wird, erfolgt nur auf der Z-Achse, um die Drehbewegung von Bowlingkugeln in der Realität nachzuahmen. Zu Beginn der Funktion wird geprüft, ob "curveLeft" wahr ist.

         
applyRotationAnimation(differenceInDistance) 
function applyRotationAnimation(differenceInDistanceValue) { 
const rotationValue = 4000 - (Math.floor(differenceInDistanceValue * 500)) 
// this changes the end rotation based on if the ball is moving left or right let endRotation 
if (curveLeft == true) { 
endRotation = 720 
} else { 
endRotation = -720 
} 
ecs.RotateAnimation.set(world, balls[currentBall], { 
autoFrom: false, 
fromX: 0, 
fromY: 0, 
fromZ: 0, 
toX: 0, 
toY: 0, 
toZ: endRotation, 
shortestPath: false, 
duration: rotationValue, 
loop: true, 
}) 
} 

      

Die Geschwindigkeit der Drehung wird durch Ändern des Werts "Dauer" der Animation geändert. Zu Beginn der Funktion wird eine Variable "rotationValue" definiert, indem 4000 subtrahiert wird vom Wert "differenceInDistance" multipliziert mit 50. Das bedeutet, je größer der Unterschied zwischen der Start- und Endposition von x ist, desto geringer ist der Rotationswert, der auf die Dauer der Animation angewendet wird (die Animation wird in kürzerer Zeit abgeschlossen). Diese Animation wird in einer Schleife abgespielt, sodass sich die Bälle ständig drehen. Es ist außerdem wichtig, dass Sie "shortestPath" auf "false" setzen, da sonst nichts zu passieren scheint. 


Am Ende der Funktion "spawnBall" wird schließlich der Wert "currentBall" geändert.

         
// Increase current ball or reset 
if (currentBall == 9) { 
currentBall = 0 
} else { 
currentBall++ 
} 

      

 

Kollisionserkennung 

Im Laufe des Spiels gibt es zwei Fälle, in denen eine Kollision erkannt wird. Einer, wenn ein Ball mit der "CollisionBox" hinter dem Pin kollidiert. Wenn diese Kollision erkannt wird, bedeutet dies, dass der Spieler einer Bowlingkugel erfolgreich ausgewichen ist und ein Punkt erzielt werden sollte. Der andere Fall ist, wenn ein Ball den Pin trifft, wodurch das Spiel beendet wird. 
Wie die meisten Dinge in diesem Projekt beginnt es mit der Erstellung einer Referenz auf das Objekt im Schema. Der Name des Objekts, das wir überprüfen möchten, ist mit etwas kollidiert und lautet "Kollision". Wir wenden dieses Objekt dann in der Szene an und erstellen eine Referenz am Anfang der Add-Funktion. 

         
schema: { 
collision: ecs.eid, 
}, 
add: (world, component) => { 
// Runs when the component is added to the world. 
const { 
collision, 
} = component.s

      

Alle Bälle sind außerdem mit einem Physik-Kollisionskörper versehen, aber der "Rigidbody" ist hier auf "Dynamic" gesetzt, da sich die Bälle bewegen. Das Kontrollkästchen "Nur Ereignis" ist hier ebenfalls aktiviert, da wir zwar eine Kollision erkennen möchten, aber nicht wollen, dass die Bälle tatsächlich mit dem Kasten interagieren und abprallen.

         
world.events.addListener(collision, ecs.physics.COLLISION_START_EVENT, handleCollision) 

      

Innerhalb der Funktion "add" wird ein Ereignis-Listener erstellt – "ecs.physics.COLLISION_START_EVENT". Diese Komponente wird zum Objekt "collision" hinzugefügt und ruft bei einer Kollision die Funktion "handleCollision" auf. Wir müssen nicht verfolgen, welches Objekt kollidiert, da in diesem Projekt nur die Bälle kollidieren können. 


Die Kollision zwischen dem Ball und dem Stift wird auf genau dieselbe Weise behandelt, aber anstatt einen Ereignis-Listener für das Objekt "collision" zu erstellen, suchen wir nach dem Objekt "pin", auf das wir bereits eine Referenz haben, da wir seine Position mit der Kopfdrehung des Benutzers steuern. Es ruft die Funktion "hitPin" auf, in der die gesamte Logik für das Endspielszenario enthalten ist. 

         
world.events.addListener(pin, ecs.physics.COLLISION_START_EVENT, hitPin) 

      

 

 anpassen

Alle diese Werte können geändert werden, indem Sie in der Szenenhierarchie "GameController" auswählen und dann zum Inspektionsfenster navigieren, wo Sie sie unter dem Skript "GameController" finden. 
Pin-Geschwindigkeit – Dies ist die Geschwindigkeit, mit der sich der Pin (der Hauptspieler) bewegt. Je höher dieser Wert ist, desto schneller bewegt es sich. Mach dir keine Sorgen, dass der Pin dadurch vom Bildschirm verschwindet, da wir seine Position fixieren. 
Initial Spawn Frequency – Dies ist die Zeit (in Millisekunden), die vergeht, bis nach dem letzten Ball ein neuer Ball erscheint. Denken Sie daran, dass dieser Wert jedes Mal reduziert wird, wenn ein Ball erscheint. Es ist daher ratsam, ihn zu Beginn des Spiels relativ hoch anzusetzen, damit es nicht zu früh zu schwierig wird.

Spawn Frequency Multiplier (Spawn-Häufigkeitsmultiplikator) – Dieser Wert wird von der Initial Spawn Frequency (Anfängliche Spawn-Häufigkeit) abgezogen. Sie können sich diesen Wert als den Grad vorstellen, in dem das Spiel schwieriger wird. Mit dem aktuellen Standardwert von 5 bedeutet dies, dass jedes Mal, wenn ein Ball erscheint, die Zeit bis zum Erscheinen des nächsten Balls um 5 Millisekunden verkürzt wird. Je höher diese Zahl ist, desto schneller wird die Spawn-Zeit reduziert und die maximale Ball-Spawn-Frequenz erreicht. Auch hier empfiehlt es sich, diesen Wert relativ niedrig zu halten, damit das Spiel nicht zu schnell zu schwierig wird. 


Spawn-Häufigkeit Minimum – Dies ist der Mindestwert, den die Spawn-Häufigkeit haben soll. Standardmäßig ist dieser Wert auf 500 Millisekunden eingestellt, was bedeutet, dass die Spawn-Verzögerung zwischen den einzelnen Bällen niemals weniger als eine halbe Sekunde beträgt. Sie können diesen Wert als maximale Schwierigkeit betrachten. Wenn Sie den Spieler wirklich auf die Probe stellen möchten, können Sie diesen Wert verringern, sodass die Bälle schneller erscheinen. 


Anfangsgeschwindigkeit des Balls – Dies ist die Zeit, die der Ball benötigt, um zum Spieler zu gelangen. Denken Sie daran, dass dieser Wert im Laufe des Spiels verringert wird, damit die Geschwindigkeit des Balls zunimmt. Der Standardwert bedeutet, dass der Ball zu Beginn der Erfahrung etwa 3 Sekunden benötigt, um den Spieler zu erreichen (abhängig von der hinzugefügten Variation). 


Ballgeschwindigkeitsvariation – Dies ist der Zufallswert, der auf die Geschwindigkeit des Balls angewendet wird, damit sich nicht alle Bälle auf dem Bildschirm mit derselben Geschwindigkeit bewegen. Mit dem Standardwert 200 bedeutet dies, dass die Geschwindigkeit des Balls zwischen 0 und 200 Millisekunden schneller sein kann. Je höher dieser Wert, desto größer die Schwankungen bei der Ballgeschwindigkeit, je niedriger der Wert, desto gleichmäßiger die Ballgeschwindigkeit. 


Wert für die Erhöhung der Ballgeschwindigkeit – Dieser Wert wird jedes Mal, wenn ein Ball erzeugt wird, von der Ballgeschwindigkeit abgezogen. Das bedeutet, dass jedes Mal, wenn ein Ball erzeugt wird, die Geschwindigkeit um 10 Millisekunden erhöht wird. Je höher diese Zahl, desto schneller erreichen die Bälle ihre Höchstgeschwindigkeit. 


Maximale Ballgeschwindigkeit – Dies ist die maximale Geschwindigkeit, mit der sich die Bälle bewegen können. Derzeit ist dieser Wert auf 2000 Millisekunden eingestellt, was bedeutet, dass unter Berücksichtigung einer möglichen Abweichung von 200 Millisekunden die kürzeste Zeit, die ein Ball benötigt, um den Spieler zu erreichen, 1800 Millisekunden beträgt. Wenn Sie diese Zahl verringern, erhöht sich die maximale Geschwindigkeit. 


Weitermachen 
Die Idee hinter dieser Vorlage war es, die grundlegenden Kernmechaniken für ein Spiel bereitzustellen. Das Beste am Entwickeln von Spielen ist, dass man jede beliebige Geschichte erzählen kann! Anstatt einfach nur die Werte dieses Spiels anzupassen, versuchen Sie doch einmal, die Geschichte zu verändern, indem Sie die Assets austauschen. Im Moment bist du eine Bowlingkegel, der auf einer Bowlingbahn Bowlingkugeln ausweichen muss, aber du könntest auch ein Skifahrer sein, der riesigen Schneebällen ausweicht, während er einen Berg hinunterfährt, oder ein Raumschiff, das Asteroiden ausweichen muss. Wenn Sie zu Schneebällen wechseln, könnten Sie vielleicht die Rotation so ändern, dass sie sich vorwärts und nicht seitwärts drehen.

Your cool escaped html goes here.