JavaScript i Engine
Engines skript-API, livssyklusen, koordinatfellene, de tre måtene å lage et objekt på, og hvordan du flytter ett uten å gå gjennom vegger.
På én linje#
Hver entitet kan bære et JavaScript-skript. Det kjører i nettleseren, i din egen fane, mot den levende scenen, og det er det kanoniske skript-API-et: BASIC-dialekten, og Python-, C#- og Rust-visningene i editoren, kompilerer alle ned til den samme overflaten.
Den uttømmende listen er API-referansen: 538 medlemmer i 50 navnerom, én side hver, med søk. Denne siden er det du trenger å vite før du leser den.
Livssyklusen#
function start() {} // once, when the entity starts
function update(dt) {} // every frame, dt in seconds
function fixedUpdate(dt) {} // fixed timestep, for physics
function onCollisionEnter(other) {} // first frame of contact
function onCollisionStay(other) {} // every frame while touching
function onCollisionExit(other) {} // contact just ended
function onTriggerEnter(other) {} // entered a trigger volume
function onTriggerExit(other) {}
function onMessage(msg, data, senderId) {} // entity-to-entity messaging
function onAnimationEvent(name, data) {}
function onDestroy() {}
function main() {} // console-game entry, async allowed
deltaTime, time, entityId og entity er globale; getComponent(type)
leser en komponent fra entiteten som eier skriptet.
Kollisjoner og triggere utløses i både 2D og 3D, og hver side mottar sin
egen kontaktnormal: other.contact.normal peker fra den andre entiteten
mot denne. Det er det som lar et skript fortelle «jeg landet på den» fra
«den landet på meg», en platformer-stomp leser
other.contact.normal.y > 0.5.
De to koordinatfellene#
Begge koster reell feilsøkingstid, og ingen av dem feiler høylytt.
Mus: side versus lerret#
input.mousePosition er i side-koordinater (page). scene.pick() vil
ha lerret-koordinater (canvas). Å sende den ene i stedet for den andre
bommer ikke, den treffer et punkt forskjøvet av viewportens posisjon i
vinduet, så en klikk-og-gå-helt går et sted som er plausibelt og feil.
Kall scene.pick() uten noe argument (den sikter mot markøren), eller bruk
input.mouseViewport når du trenger tallene.
Virtuelle kontroller er i lerretpiksler#
input.addVirtualJoystick(id, x, y, size) og input.addVirtualButton(...)
plasserer sentrene sine i det samme rommet som mouseViewport. En joystick
returnerer en normalisert X/Y etter sin radiale dødsone; en knapp eksponerer
holdt, trykket-denne-rammen og sluppet-denne-rammen hver for seg.
Pekeren deres fanges opp og forbrukes, så en berøring på kontrollen
rapporteres ikke også som en rå lerret-handling.
Standard-joysticken er samlet.
input.getJoystickX/Y()velger én komplett vektor fra skjerm-spaken, en fysisk kontroller, eller tastaturet (WASD/piltaster), avhengig av hvilken kilde som er sterkest. En inaktiv tilkoblet kontroller deaktiverer derfor ikke tastaturbevegelse. Y-aksen dens følger 2D-skjermrom: opp er-1.
Tre måter å lage et objekt på, og de er ikke utskiftbare#
| Hva den lager | Lever så lenge som | |
|---|---|---|
scene.createEntity(def) | en forfattet entitet: den vises i Scene Graph og i Inspector | prosjektet, den lagres |
game.spawn(type, pos) | en bar primitiv: ingen helse, ingen AI, ingen atferd | spilløkten |
game.spawnFrom(template, pos, opts) | en kopi av en hel entitet: komponenter, fysikk-kropp, tags, lag, skala og den kompilerte atferdsstabelen | spilløkten |
game.spawn er riktig for rusk og prototyper og ubrukelig for fiender:
en spawner matet av den produserer livløse kuler. Malen spawnFrom kopierer,
er en ordinær entitet du setter sammen i editoren og slår av med hierarkiets
øye: ikke noe eget format, ikke noen ny editor, så det du ser, er det som
dukker opp.
// Once, at start: a missing template should say so, not fail every wave silently
if (!game.hasTemplate('Skeleton')) console.warn('no Skeleton template');
const mob = game.spawnFrom('Skeleton', { x, y, z }, { tag: 'Enemy' });
template godtar en id, et navn eller en tag. Kopier laget under spilling
er begrenset til spilløkten, så stop() fjerner dem, og redigeringsscenen
forurenses aldri.
Å slå av en entitet betyr skjult OG stille: node deaktivert, skript stoppet, fysikk-kropp svarer ikke lenger. Å bare skjule den ville latt en usynlig fiende fortsatt treffe deg.
game.setEnabled(id, on)styrer det fra et skript, øyeikonet styrer det fra hierarkiet.
Å flytte noe: skyv en kropp, ikke teleporter#
Å skrive transform.position hver ramme går gjennom vegger, gjennom andre
monstre og gjennom gulvet. Styr hastigheten i stedet, men bare når det
finnes noe å styre:
if (physics.hasBody) {
const v = physics.getVelocity();
physics.setVelocity({ x: vx, y: v.y, z: vz }); // pushes a real body
} else {
transform.position.x += vx * dt; // legitimate for a flyer
}
physics.setVelocity uten en kropp fyller et felt ingen integrerer, og
entiteten stopper dødt. Det er derfor physics.hasBody finnes, og hvorfor
hver bevegelig atferd i katalogen stiller spørsmålet i stedet for å anta et
svar. Å stoppe betyr å nullstille hastigheten: å ikke gjøre noe lar
kroppen fortsette å seile.
Å skrive en posisjon flytter nå faktisk en fysikk-kropp. Havok styrer transformasjonen, aldri omvendt, så å tilordne
transform.positionpå en dynamisk kropp ble tidligere overskrevet på neste steg: hver teleportering feilet stille på en fysisk entitet. Posisjons-proxyen synkroniserer nå kroppen på nytt, slik rotasjons-proxyen alltid har gjort.
Pathfinding er et øyeblikksbilde#
pathfinding.createGrid() raycaster et rutenett én gang, sentrert der
den ble kalt. Å forlate den boksen returnerer null, og de fleste kallere
faller da tilbake på en rett linje, gjennom vegger, uten et ord.
Rutenettet sentrerer seg på nytt på den forespurte reisen som standard.
setAutoRecenter(false) reserverer seg mot det på en fast verden, der
gjenoppbygging koster en raycast-omgang for ingenting.
console.log logger. Print tegner.#
Konsollen er console.log / warn / error, som hvor som helst ellers.
BASIC-ens Print tegner på skjermen og kalles hver ramme, de to er
bevisst separate kommandoer, og å blande dem er
det som fyller en konsoll med en rammesløyfe.
Hvor et skript kjører#
I editoren og i et web-bygg kjører skript i nettleseren. I et native desktop- eller mobilbygg kjører de uendret på en innebygd QuickJS-runtime, den samme kilden, ikke en portering.
Skript lagres i nettleserens egen database mens du redigerer, så en ikke- lagret buffer overlever en omlasting; de lagres inn i prosjektet med alt annet.
Begrensninger og vanlige fallgruver#
scene.pick()med et argument vil ha lerretkoordinater. Se over; det er den vanligste feilen med feil sted.game.spawnlager en primitiv, ikke en karakter. BrukspawnFrom.- En kropp opprettes for entiteter født midt i spillet. Fysikk ble tidligere bare bygget ved Play, så alt som ble spawnet etterpå, falt stille gjennom verden mens de håndplasserte naboene oppførte seg normalt.
- Åtte steg er AI-lagkameratens tak, ikke ditt. En skriptsløyfe har
ingen slik grense; en løpsk
whilevil henge rammen som hvor som helst ellers. - De fire andre språkvisningene er transpilert fra denne. Å redigere en Python- eller Rust-visning og bytte tilbake går gjennom den lagrede JavaScript-en, se BASIC-siden for hvorfor.