Engine-இல் JavaScript

Engine-இன் script API லைஃப்சைக்கிள், coordinate traps, ஒரு object-ஐ உருவாக்கும் மூன்று வழிகள், மற்றும் சுவர்கள் வழியாக நடக்காமல் ஒன்றை நகர்த்துவது எப்படி.

ஒரே வரியில்#

ஒவ்வொரு entity-உம் ஒரு JavaScript script-ஐ சுமக்க முடியும். இது உலாவியில், உங்கள் tab-இல், live scene-க்கு எதிராக இயங்குகிறது, மேலும் இது canonical scripting API: BASIC dialect, மற்றும் editor-இல் உள்ள Python, C# மற்றும் Rust காட்சிகள் அனைத்தும் அதே surface-க்கு compile ஆகின்றன.

முழுமையான பட்டியல் API reference: 50 namespaces-இல் 538 members, ஒவ்வொன்றும் ஒரு பக்கம், ஒரு தேடலுடன். இந்தப் பக்கம், அதைப் படிப்பதற்கு முன் நீங்கள் தெரிந்துகொள்ள வேண்டியது.

Lifecycle#

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 மற்றும் entity globals; getComponent(type), script-ஐ சொந்தமாக்கியிருக்கும் entity-இலிருந்து ஒரு component-ஐ படிக்கிறது.

Collisions மற்றும் triggers 2D-இலும் 3D-இலும் இயங்கும், மேலும் ஒவ்வொரு பக்கமும் அதற்கே உரிய contact normal-ஐ பெறும்: other.contact.normal, other entity-இலிருந்து இதை நோக்கி புள்ளிகாட்டுகிறது. "நான் அதன் மேல் இறங்கினேன்" என்பதை "அது என் மேல் இறங்கியது" என்பதிலிருந்து ஒரு script சொல்ல அனுமதிப்பது இதுதான், ஒரு platformer stomp other.contact.normal.y > 0.5 என்று படிக்கிறது.

இரண்டு coordinate traps#

இரண்டும் உண்மையான debugging நேரத்தை செலவழிக்கின்றன, மேலும் இரண்டும் சத்தமாக தோல்வியடையாது.

Mouse: page vs canvas#

input.mousePosition page coordinates-இல் உள்ளது. scene.pick() canvas coordinates-ஐ விரும்புகிறது. ஒன்றை மற்றொன்றுக்குப் பதிலாக அனுப்புவது தவறவிடாது, அது சாளரத்தில் viewport-இன் இடத்தால் offset செய்யப்பட்ட ஒரு புள்ளியில் தாக்குகிறது, எனவே ஒரு click-to-move hero, நம்பத்தகுந்த ஆனால் தவறான ஒரு இடத்திற்கு நடக்கிறார்.

argument இல்லாமல் scene.pick()-ஐ அழைக்கவும் (இது cursor-ஐ நோக்குகிறது), அல்லது எண்கள் தேவைப்படும்போது input.mouseViewport-ஐ பயன்படுத்தவும்.

Virtual controls canvas pixels-இல் உள்ளன#

input.addVirtualJoystick(id, x, y, size) மற்றும் input.addVirtualButton(...), தங்கள் centres-ஐ mouseViewport அதே இடத்தில் வைக்கின்றன. ஒரு joystick, அதன் radial dead zone-க்குப் பிறகு ஒரு normalised X/Y-ஐ தரும்; ஒரு button held, pressed-this-frame மற்றும் released-this-frame-ஐ தனித்தனியாக வெளிப்படுத்தும். அவற்றின் pointer capture செய்யப்பட்டு consume செய்யப்படுகிறது, எனவே control-இன் மேல் ஒரு தொடுதல், ஒரு raw canvas action ஆகவும் தெரிவிக்கப்படாது.

இயல்பு joystick ஒருங்கிணைக்கப்பட்டது. input.getJoystickX/Y(), on-screen stick, ஒரு physical gamepad, அல்லது keyboard (WASD/arrows) ஆகியவற்றில் எது வலிமையானதோ அதிலிருந்து ஒரு முழுமையான vector-ஐ எடுக்கிறது. எனவே செயலற்ற ஒரு இணைக்கப்பட்ட pad, keyboard இயக்கத்தை முடக்காது. அதன் Y axis 2D screen space-ஐ பின்பற்றுகிறது: மேல் -1.

ஒரு object-ஐ உருவாக்கும் மூன்று வழிகள், அவை ஒன்றுக்கொன்று மாற்றக்கூடியவை அல்ல#

அது என்ன உருவாக்குகிறதுஎதற்காக வாழ்கிறது
scene.createEntity(def)ஒரு authored entity: இது Scene Graph-இலும் Inspector-இலும் தோன்றும்திட்டம், இது சேமிக்கப்படும்
game.spawn(type, pos)ஒரு bare primitive: health இல்லை, AI இல்லை, behaviour இல்லைplay session
game.spawnFrom(template, pos, opts)ஒரு முழு entity-இன் நகல்: components, physics body, tags, layer, scale மற்றும் compile செய்யப்பட்ட behaviour stackplay session

game.spawn debris மற்றும் prototypes-க்கு சரியானது, மேலும் enemies-க்கு பயனற்றது: அதனால் ஊட்டப்படும் ஒரு spawner, செயலற்ற பந்துகளை உருவாக்கும். spawnFrom நகலெடுக்கும் template, நீங்கள் editor-இல் compose செய்து hierarchy-இன் eye-ஆல் அணைக்கும் ஒரு சாதாரண entity: தனி வடிவம் இல்லை, இரண்டாவது editor இல்லை, எனவே நீங்கள் பார்ப்பதுதான் தோன்றுவது.

// 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, ஒரு id, ஒரு பெயர் அல்லது ஒரு tag-ஐ ஏற்கும். play-இன் போது செய்யப்படும் நகல்கள் play-scoped, எனவே stop() அவற்றை அகற்றும், மேலும் edit scene ஒருபோதும் அசுத்தமாகாது.

ஒரு entity-ஐ அணைப்பது என்றால் மறைந்ததும் AND அமைதியானதும்: node disabled, script நிறுத்தப்பட்டது, physics body இனி பதிலளிக்காது. மறைப்பது மட்டும் ஒரு கண்ணுக்குத் தெரியாத எதிரி இன்னும் உங்களைத் தாக்கும்படி விட்டுவிடும். game.setEnabled(id, on) ஒரு script-இலிருந்து இதை இயக்குகிறது, eye icon hierarchy-இலிருந்து இதை இயக்குகிறது.

ஏதேனும் ஒன்றை நகர்த்துதல்: ஒரு body-ஐ push செய்யுங்கள், teleport செய்யாதீர்கள்#

ஒவ்வொரு frame-உம் transform.position-ஐ எழுதுவது சுவர்கள் வழியாகவும், மற்ற monsters வழியாகவும், தரை வழியாகவும் நடக்கிறது. அதற்குப் பதிலாக velocity-ஐ இயக்குங்கள், ஆனால் இயக்க ஏதேனும் இருக்கும்போது மட்டும்:

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
}

ஒரு body இல்லாமல் physics.setVelocity, யாரும் integrate செய்யாத ஒரு field-ஐ நிரப்புகிறது, மேலும் entity நின்றுவிடும். இதனால்தான் physics.hasBody இருக்கிறது, மேலும் இதனால்தான் catalogue-இல் உள்ள ஒவ்வொரு moving behaviour-உம், ஒரு பதிலை எடுத்துக்கொள்ளாமல் கேள்வியைக் கேட்கிறது. நிறுத்துவது என்றால் velocity-ஐ ரத்து செய்வது: எதுவும் செய்யாமல் இருப்பது body-ஐ coast செய்யவே விடும்.

ஒரு position-ஐ எழுதுவது இப்போது ஒரு physics body-ஐ நகர்த்தும். Havok transform-ஐ இயக்குகிறது, ஒருபோதும் நேர்மாறாக இல்லை, எனவே ஒரு dynamic body-இல் transform.position-ஐ assign செய்வது முன்பு அடுத்த step-இல் overwrite செய்யப்படும்: ஒரு physical entity-இல் ஒவ்வொரு teleport-உம் அமைதியாக தோல்வியடையும். position proxy body-ஐ மீண்டும் sync செய்கிறது, rotation proxy எப்போதும் செய்தது போலவே.

Pathfinding ஒரு snapshot#

pathfinding.createGrid(), அது அழைக்கப்பட்ட இடத்தில் மையப்படுத்தப்பட்ட ஒரு கிரிட்டை ஒருமுறை raycast செய்கிறது. அந்த box-ஐ விட்டு வெளியேறுவது null-ஐ தரும், மேலும் பெரும்பாலான callers பிறகு ஒரு வார்த்தையும் இல்லாமல், சுவர்கள் வழியாக, ஒரு நேர்கோட்டிற்குத் திரும்புகின்றன.

கிரிட் இயல்பாகவே கோரப்பட்ட பயணத்தில் மீண்டும் மையப்படுத்தப்படும். ஒரு நிலையான உலகில், மீண்டும் கட்டமைப்பது வீணாக ஒரு raycast pass-ஐ செலவழிக்கும் இடத்தில், setAutoRecenter(false) இதைத் தவிர்க்கிறது.

console.log log செய்யும். Print வரையும்.#

console என்பது console.log / warn / error, மற்ற எங்கும் போலவே. BASIC Print திரையில் வரைகிறது, மேலும் ஒவ்வொரு frame-உம் அழைக்கப்படுகிறது, இரண்டும் வேண்டுமென்றே தனித்தனி commands, மேலும் அவற்றைக் குழப்புவதுதான் ஒரு console-ஐ ஒரு frame loop-உடன் நிரப்புகிறது.

Script எங்கு இயங்குகிறது#

editor-இலும் ஒரு web build-இலும், scripts உலாவியில் இயங்குகின்றன. ஒரு native desktop அல்லது mobile build-இல், அவை ஒரு embedded QuickJS runtime-இல், மாறாமல், அதே source-ஆக, ஒரு port அல்லாமல் இயங்குகின்றன.

நீங்கள் எடிட் செய்யும்போது Scripts உலாவியின் சொந்த database-இல் சேமிக்கப்படுகின்றன, எனவே சேமிக்கப்படாத ஒரு buffer ஒரு reload-ஐ தாண்டி நிலைத்திருக்கும்; அவை மற்ற எல்லாவற்றுடனும் திட்டத்திற்குள் சேமிக்கப்படுகின்றன.

வரம்புகளும் பொதுவான சிக்கல்களும்#

  • ஒரு argument-உடன் scene.pick() canvas coordinates-ஐ விரும்புகிறது. மேலே பார்க்கவும்; இதுவே மிகவும் பொதுவான தவறான-இட பிழை.
  • game.spawn ஒரு primitive-ஐ உருவாக்குகிறது, ஒரு character-ஐ அல்ல. spawnFrom-ஐ பயன்படுத்தவும்.
  • விளையாட்டின் நடுவில் பிறக்கும் entities-க்கு ஒரு body உருவாக்கப்படுகிறது. Physics முன்பு Play-இல் மட்டுமே கட்டமைக்கப்படும், எனவே பின்னர் spawn செய்யப்பட்ட எதுவும் அதன் கையால் வைக்கப்பட்ட அண்டைவீட்டார் சரியாக நடந்துகொள்ளும்போது, அமைதியாக உலகின் வழியாக விழுந்துவிடும்.
  • எட்டு படிகள் AI teammate-இன் உச்சவரம்பு, உங்களுடையது அல்ல. ஒரு script loop-க்கு அப்படி எந்த வரம்பும் இல்லை; ஒரு கட்டுப்பாடற்ற while, மற்ற எங்கும் போலவே frame-ஐ hang செய்யும்.
  • மற்ற நான்கு மொழி காட்சிகளும் இதிலிருந்து transpile செய்யப்படுகின்றன. ஒரு Python அல்லது Rust காட்சியை எடிட் செய்து திரும்ப மாறுவது, சேமிக்கப்பட்ட JavaScript வழியாகச் செல்கிறது, ஏன் என்று BASIC பக்கம் பார்க்கவும்.