Webworker에서 JS 물리적 - 개념 증명 실행
16223 단어 webdevgamedevtypescriptjavascript
시리즈: Javascript 물리적 세계 탐색
Web Workers는 기본 스레드에서 컴퓨팅 집약적 작업을 제거하는 데 유용한 방법입니다.나는 그것들을 사용하는 것에 흥미를 느낀 지 이미 오래되었지만, 내가 종사하는 프로젝트 중 그것들을 사용하는 것이 합리적이라는 것을 진정으로 증명하는 것은 하나도 없다.지금까지!이 짧은 시리즈에서, 나는 웹워크스, 물리학,pixi를 어떻게 사용하는지 탐색할 것이다.js와 다른 사람들이 인터랙티브 네트워크 체험과 게임을 만듭니다.
네트워크 작업자 tldr;
깊이 있는 정보는 내가 설명할 수 있는 것보다 낫다.
왜?
인터넷 종사자를 사용하는 장점은 부인할 수 없다.가장 중요한 것은 주 라인의 응답성을 유지하는 것이다.동결된 웹 페이지와 느린 사용자 인터페이스는 나쁜 사용자 체험을 가져올 수 있다.나의 예에서 물리 시뮬레이션 속도가 20-30fps로 낮아져도 메인 라인 렌더링기는 여전히 고정된 144fps로 운행한다.이것은 애니메이션을 아름답고 생동감 있게 유지하고 페이지가 사용자의 입력에 응답하는 데 도움이 된다.
나는 과거의 CPU 집약형 지형 생성에 대해 죄책감을 느꼈다. 그것은 사용자의 브라우저를 2-3초 동안 동결시켰다. 이것은 매우 나쁘다.
개념 증명 구현:
이것은 순서에 따라 점진적인 강좌가 아니다. 나는 이 문장을 더욱 개념적이고 코드가 간결하게 하고 싶다.너는 the project repo에서 나의 스파게티 코드를 따를 수 있을 것이다.
1. 위트 포장기
나는 불필요한 복잡성을 피하기 위해 어떤 틀도 사용하지 않기로 결정했다.번들에 대해 Vite를 사용하기로 결정했습니다and the provided vanilla Typescript template.Typescript 파일에서 easy way to import webworkers 및 종속 항목까지 제공합니다.
2.피시.js 렌더링
Pixi.js는 상당히 사용하기 쉬운 WebGL 렌더링입니다.그것은 화면에 우리가 무엇을 하고 있는지 나타낼 것이다.내가 한 모든 것은 복제the examples 중 하나를 통해 복제할 수 있다.당신은 단지:
3. 마지막으로 일꾼을 성공시키자!
physicsWorker.ts
.코드는 작업 부하 시 실행됩니다.4. 일꾼 중의 물리 엔진.
Matter.js는 내가 사용하기로 결정한 2D 물리 엔진이다.그것은 성능이 가장 좋은 것은 아니지만 사용자에게 친절하고 코드의 복잡도를 낮추는 데 도움이 된다.
엔진, 세계, 게임 순환은 웹 워크맨이 불러올 때 생성됩니다.Gameloop은 연속적으로 실행되고 호출되는 함수입니다.
Engine.update(physics.engine, delta);
5. 소통과 지휘 모드
앞서 언급한 바와 같이 워크맨과 라인은 메시지를 통해 통신한다.나는 이것이 자연적으로 적합하다는 것을 발견했다. command pattern
Actor(주 스레드 또는 작업 스레드)는 바디 작업을 수행하는 데 필요한 모든 정보를 포함하는 객체를 보냅니다.나는 아래와 같이 나의 명령을 조직하기로 결정했다.
const command = {
type: "ADD_BODY",
data: {
x: 0,
y: 0,
width: 10,
height: 10,
options: {
restitution: 0,
},
},
};
상기 명령을 보내려면 주 스레드 호출worker.postMessage(command);
.직원들이 그것을 받아들일 수 있도록, 우리는 탐지기를 설치해야 한다.// Worker has to call 'self' to send and receive
self.addEventListener("message", (e) => {
const message = e.data || e;
// Worker receives a command to ADD_BODY
if (message.type == "ADD_BODY") {
// it does stuff
const { x, y, width, height, options } = message.data;
const body = physics.addBody(x, y, width, height, options);
// Worker sends a command to main thread (BODY_CREATED)
// it will be used to spawn a sprite
self.postMessage({
type: "BODY_CREATED",
data: {
id: body.id,
x,
y,
width,
height,
angle: 0,
sprite: undefined,
},
});
}
});
다음은 이 예의 작업 원리의 개술이다6. 기능 설명
신체를 창조하다
ADD_BODY
ADD_BODY
을 수신할 때 주어진 파라미터를 가진 주체를 세계에 추가BODY_CREATED
명령을 주 라인으로 보냅니다.이 메시지의 가장 중요한 부분은 id입니다. 기술적으로 관련이 없는 자바스크립트 대상 (worker의 바디와main의sprite) 이 어떻게 동기화되는지입니다.또한 폭, 높이, 위치 및 각도BODY_CREATED
위치를 수신할 때 수신된 데이터와 분배된 PIXI.Sprite
위치를 포함하는 대상을 만듭니다.물리적 엔진과 렌더기 간에 객체 위치 동기화
BODY_SYNC
을 보내는데 물리 세계의 모든 물체의 위치와 각도를 포함한다.이것은hashmap 형식으로 저장되며 주체 id는 키입니다.const data: any = {};
for (const body of world.bodies) {
data[body] = {
x: body.position.x,
y: body.position.y,
angle: body.angle,
};
}
self.postMessage({
type: "BODY_SYNC",
data,
});
BODY_SYNC
.이전에 추가한 모든 엔티티를 순환하고 업데이트합니다.if (e.data.type == "BODY_SYNC") {
const physData = e.data.data;
bodySyncDelta = e.data.delta;
for (const obj of physicsObjects) {
const { x, y, angle } = physData[obj.id];
if (!obj.sprite) return;
obj.sprite.position.x = x;
obj.sprite.position.y = y;
obj.sprite.rotation = angle;
}
}
정말 쓸모가 있다!
다음과 같은 문제가 발생했습니다.
미래의 개선 고려
1. 중요합니다.js가 느려요.
this outdated benchmark 사건에 의하면.js는 사용 가능한 속도가 가장 느린javascript 물리 엔진 중의 하나입니다.그 이후로 성능이 향상되었지만 다른 선택이 있었다.저는 js가 연결된 WASM 쿠터에 관심이 없습니다. 예를 들어
box2dwasm - WASM으로 컴파일된 오래되고 유지보수된 C++ 라이브러리입니다.문서가 부족해서 개발자의 경험이 매우 나쁜 것 같다.
rapier.rs-현대물리도서관은 녹으로 쓴다.그것은 보기에도 좋고 성능도 좋아서 언뜻 보기에 개발자의 체험은box2d보다 훨씬 좋다.Documentation 희망을 주셨어요!
2. 인터넷 종사자 정보
작업 라인과 주 라인 사이에 고주파(gameloop)로 메시지를 통해 대량의 데이터를 보내면 성능이 크게 떨어질 수 있다.
이 문제를 깊이 있게 탐구한다: "Is postmessage slow?" - surma.dev
고려 사항:
3. 일반적인 실현이 아닌 웹 워크맨 라이브러리 사용
나는 일반 인터넷 종사자와의 소통이 매우 복잡해질 것이라고 상상할 수 있다.Comlink 이미 내 명세서에 한동안 열거되어 있으니 한번 해 보고 싶다.
출처:
Comlink는 인터넷 종사자들을 즐겁게 한다.컴링크는 작은 도서관(1.1kB)으로 포스트 메시지에 대한 심리적 장애를 없애고 직원들과 협력하고 있다는 사실을 숨긴다.
좀 더 추상적인 측면에서postMessage와 ES6 에이전트의 RPC 구현이다.
Comlink Github 페이지 4. 렌더링 보간
만약 용례가 더 필요하지 않다면, 나는 물리 엔진을 초당 30 또는 60 프레임에 잠글 수 있다.문제는 이 운동이 보기에 파도가 거세다는 것이다.
나는 삽입값을 사용하여 사용 가능한 위치와 속도 데이터를 사용하여 대상의 운동을 예측하고 144fps에 달하는 프레임을 생성하여 매끄러운 애니메이션을 실현할 수 있다.
끝났어.
결과는 내가 예상한 것보다 훨씬 길었다.더 많아요?
Reference
이 문제에 관하여(Webworker에서 JS 물리적 - 개념 증명 실행), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/jerzakm/running-js-physics-in-a-webworker-part-1-proof-of-concept-ibj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)