Can't lock pointer back immediately after escape 오류 해결하는 방법

Nevgiveup·2025년 5월 15일
0

오류 해결

목록 보기
2/2
post-thumbnail

0. 들어가기

R3F로 웹 게임을 제작하다가 Can't lock pointer back immediately after escape라는 오류를 만났습니다.. 이 오류는 LockPointerAPI라는 API를 쓸때 나는 오류입니다.. 마우스 커서가 Lock되있는 상태에서 사용자가 ESC를 누르고 다시 바로 상호작용시 오류가 나는 문제입니다. 해당 오류는 크게 2가지 정도 해결 방법이 있는 것을 알게 되었는데 그것을 정리해보고자 합니다.

1. 버튼 만들기

https://sbcode.net/threejs/follow-cam/
이 방법은 Three.js 공식 사이트 튜토리얼 예제에서 쓴 방법입니다. PointerLock이 걸리고 ESC를 누르면 화면이 뿌애지면서 Click to Start라는 버튼을 표시합니다.

그리고 이 버튼을 클릭해야만 다시 Pointer Lock이 작동을 합니다. 저는 이방법으로 해결을 했습니다.

구현 코드

{pointerLocked ? null : (
    <ClicktoStart reqInside={reqInside} pointerLocked={pointerLocked}/>
)}
컴포넌트
import React, { useEffect, useState } from 'react';
import CTSbutton from './CTSbutton';

const ClicktoStart = ({ reqInside, pointerLocked }) => {
  const [visible, setVisible] = useState(false);
  useEffect(() => {
    const timeout = setTimeout(() => {
      setVisible(true);
    }, 1000);
    return () => clearTimeout(timeout);
  }, []);

  const handleClick = (e) => {
    if (pointerLocked) {
      e.preventDefault();
      return;
    }
  };

  return (
    <div
      onClick={handleClick}
      style={{
        width: '100%',
        height: '100%',
        opacity: 0.65,
        backgroundColor: 'black',
        zIndex: 50,
        position: 'absolute',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        pointerEvents: 'none',
      }}
    >
      <CTSbutton onClick={reqInside} visible={visible}></CTSbutton>
    </div>
  );
};

export default ClicktoStart;

pointerLocked는 포인터가 잠긴 상태면 true, 아니면 false입니다. CTSbutton은 단순 버튼 컴포넌트입니다.

2. 시간차 두기

두 번째 방법은 inactivatePointerLock()이 호출될때 최근 pointer Lock이 활성화된 시점과 현재 시간의 차이를 계산해서 만약에 100ms보다 작으면 그냥 return을 해주는 코드입니다. 사용자가 너무 빨리 잠금해제/클릭을 하면 그것을 막을 수 있다고 합니다. 저는 어떻게 구현해야할지 이해가 안가서 첫 번째 방법을 사용해 해결했습니다.

let pointerLockActivatedAt = null;

function inactivatePointerLock() {
    const now = performance.now()
    if (pointerLockActivatedAt != null && now - pointerLockActivatedAt < 100) {
        return // 무시
    }
    // do your thing
}
function activatePointerLock() {
    const now = performance.now()
    pointerLockActivatedAt = now
}

이렇게 마치겠습니다. 오늘도 고생하셨습니다.

profile
while( true ) { study(); }

0개의 댓글