로블록스 Raycast가 nil일 때: 목적지·방향·길이부터 분리하는 점검법
대상이 눈앞에 있는데 Raycast가 nil이거나 엉뚱한 곳을 맞히나요? 먼저 월드 목적지와 방향 벡터를 분리하고 길이가 목표까지 닿는지 계산합니다. 그다음 필터와 실행 환경을 하나씩 비교하면 한 번에 여러 설정을 바꾸는 시행착오를 줄일 수 있습니다.
‘코드에서 오류가 남’과 ‘코드는 실행됐지만 결과가 nil임’은 다음 확인이 다릅니다. 이 글은 목적지와 방향을 혼동하지 않도록 좌표 계산을 재현하고, 그다음 실제 프로젝트에서 필터·실행 위치를 하나씩 확인하는 순서입니다. 아래 계산과 생성 코드는 브라우저에서 검사했으며 Roblox Studio의 적중 실험은 수행하지 않았습니다.
1. 첫 출력·nil·다른 대상 적중을 분리합니다
| 현재 관찰 | 먼저 확인 | 다음 단계 |
|---|---|---|
| 첫 print도 없거나 빨간 오류가 남 | Script 종류·실행 위치, 객체 변수 준비 여부와 첫 오류 | Output·F9 로그 확인 후 Raycast 호출에 도달하는지 구분 |
| 호출 뒤 nil 분기로 들어감 | 시작점·방향·거리, 해당 실행 환경의 검사 후보 | 좌표 계산을 먼저 고정하고 필터 조건을 하나씩 비교 |
| 무언가 맞지만 목표와 다름 | 결과 Instance와 실제 교차 위치 | ‘Hit’ 문구만 보지 말고 자신·효과·앞쪽 물체를 맞힌 것인지 확인 |
| Studio 서버에서는 되고 클라이언트에서는 다름 | 각 실행 측에 존재하는 객체와 같은 좌표·조건인지 | 클라이언트 Streaming과 서버 판정을 별도로 확인 |
한 번에 길이와 필터를 모두 바꾸면 무엇이 결과를 바꿨는지 알기 어렵습니다. 우선 좌표 한 쌍과 설정을 기록하고, 바꾼 항목을 한 가지로 제한합니다. 실제 Place의 로그를 보지 않았다면 ‘필터 탓’이나 ‘엔진 버그’라고 먼저 결론 내리지 않습니다.
2. 목적지 좌표 대신 ‘목적지−시작점’을 넣습니다
시작점 O=(10,5,-3), 목적지 T=(13,5,1)을 설명용으로 정합니다. 방향에 들어갈 차이는 D=T−O=(3,0,4), 길이는 √(3²+0²+4²)=5 studs입니다. 따라서 계획한 끝점은 O+D=T로 돌아옵니다.
시작점 O = (10, 5, -3)
목적지 T = (13, 5, 1)
방향 D = (13-10, 5-5, 1-(-3)) = (3, 0, 4)
길이 |D| = 5
끝점 O+D = (13, 5, 1)
Workspace:Raycast(origin, direction, params)의 두 번째 인수는 월드 목적지 그 자체가 아닙니다. 이 예에서 (13,5,1)을 그대로 방향에 넣으면 계획 끝점은 (23,10,-2)가 됩니다. 도구가 보여 주는 방향과 내 코드에서 실제 전달하는 두 번째 값을 서로 비교하세요.
단위 벡터만 넣는 경우도 따로 봅니다. D/|D|=(0.6,0,0.8)의 길이는 1이므로 시작점에서 (10.6,5,-2.2)까지만 뻗는 계산입니다. 같은 방향으로 5 studs가 필요하면 단위 방향에 길이 5를 곱합니다. 길이 0인 경우에는 정규화부터 시도하지 말고 시작점과 목적지를 다시 선택합니다.
이 숫자는 독립 산술로 검산한 계획 좌표입니다. 물체의 표면 크기·배치·충돌 형상과 엔진 정밀도를 반영한 적중 지점이 아닙니다. 계산이 맞아도 실제 대상이 해당 선분과 교차하는지와 검사 후보인지는 별도입니다.
3. 같은 계산인지 확인하는 브라우저 예제 5개
2026-10-31 Windows Edge 156.0.4314.50에서 Raycast 생성기의 실제 폼에 아래 값을 넣었습니다. Water 무시·Default 충돌 그룹·RespectCanCollide 꺼짐은 기본값을 유지했고 필터는 없음으로 선택했습니다. 방향·길이 출력과 같은 점 입력의 오류를 확인했으며 실제 Ray를 발사한 결과가 아닙니다.
| 비교 입력 | 실제 출력 |
|---|---|
| 기준 3·4·5 삼각형 시작점(10,5,-3) · 목적지(13,5,1) · 필터 없음 | Vector3.new(3, 0, 4) / 5 studs |
| 양 끝을 같은 만큼 이동 시작점(-7,25,9) · 목적지(-4,25,13) · 필터 없음 | Vector3.new(3, 0, 4) / 5 studs |
| 시작점과 목적지 교환 시작점(13,5,1) · 목적지(10,5,-3) · 필터 없음 | Vector3.new(-3, 0, -4) / 5 studs |
| 같은 방향으로 두 배 시작점(10,5,-3) · 목적지(16,5,5) · 필터 없음 | Vector3.new(6, 0, 8) / 10 studs |
| 같은 점 입력 시작점·목적지 모두(10,5,-3) | 시작점과 목적지가 같습니다. 길이가 0보다 큰 Ray가 되도록 목적지 좌표를 바꿔 주세요. |
두 점을 같은 만큼 옮기면 차이 벡터는 그대로이고, 두 점을 교환하면 부호가 바뀝니다. 같은 방향으로 차이를 두 배로 만들면 길이도 두 배가 됩니다. 이 세 비교로 ‘좌표 자체’와 ‘두 점 사이의 차이’를 구분할 수 있습니다. 도구에서 좌표·옵션을 바꾸면 이전 생성 결과를 숨기므로 다시 생성해 새 값을 확인합니다.
입력·예상값·출력 원문 보기 → · 이 도구의 좌표 ±1,000,000과 변수 8개 제한은 입력 실수를 줄이는 도구 범위입니다. 공식 Raycast 길이 상한 15,000 studs와 구분합니다. 도구의 필터 없음도 물·충돌·조회 조건까지 전부 무시한다는 뜻은 아닙니다.
4. 계산이 맞으면 필터·조회 조건을 한 단계씩 봅니다
프로젝트 전체의 설정을 바꾸기 전에 소유한 테스트 Place에서 목표 Part 하나와 고정 좌표를 준비합니다. 원래 프로젝트의 필터와 속성값을 적어 둔 다음, 한 가지 조건만 바꾸고 결과 Instance·Position·Distance 또는 nil을 기록합니다. 아래는 따라 할 비교 계획이며 이 사이트가 Studio에서 측정한 결과표가 아닙니다.
| 순서 | 비교 항목 | 구분할 해석 |
|---|---|---|
| ① 좌표 | 시작점·목적지·차이·길이를 고정 | 길이가 목표까지 닿는지와 방향을 먼저 분리 |
| ② Instance 목록 | Include·Exclude 목록의 실제 Instance와 자손 관계 | Include 빈 배열은 아무 대상도 포함하지 않음. 변수 이름 문자열을 Instance처럼 넣지 않기 |
| ③ Part 조회 | 목표의 CanQuery·CanCollide와 params.RespectCanCollide | 서로 다른 속성을 한 번에 바꾸지 않기. BasePart 문서는 CanQuery 효과에 CanCollide 비활성 조건을 명시 |
| ④ 물·충돌 그룹 | IgnoreWater와 Raycast가 사용하는 CollisionGroup | Terrain Water 제외와 충돌 그룹 관계를 Instance 목록 필터와 구분 |
| ⑤ 실행 측 | 같은 조건을 서버·클라이언트에서 각각 기록 | 클라이언트에 대상이 실제 존재하는지 먼저 확인. 서버와 같은 객체 집합이라고 가정하지 않기 |
현재 RaycastParams의 IncludeInstances와 ExcludeInstances는 목록의 객체와 자손 범위를 사용합니다. 둘에 모두 해당하면 제외가 우선입니다. IncludeInstances=nil과 {}은 같은 설정이 아닙니다. 도구는 Include 목록이 비어 있으면 코드를 만들지 않으며, 제공받은 변수에 실제 Instance가 들어 있는지까지 실행 확인하지는 않습니다.
CanCollide=false는 걷다가 통과할 수 있는 조건과 관련되고, 공간 질의의 포함 조건은 CanQuery와 params 설정도 봐야 합니다. RespectCanCollide=true를 쓴 상태를 기본값과 섞어 비교하지 마세요. 충돌을 강제로 무시하는 옵션으로 결론을 덮기보다 현재 설정의 이유를 확인합니다.
5. nil과 ‘목표가 없음’을 같은 결론으로 쓰지 않습니다
결과가 있다면 Instance·Position·Distance를 함께 봅니다. 5 studs를 계획했는데 결과 Distance가 2라면 어떤 물체가 먼저 교차한 것인지 조사할 단서가 됩니다. 목표 이름만으로 성공을 판단하지 말고 기대한 객체·표면인지 확인합니다. 이는 결과를 읽는 기준이며 위 예제가 실제 2 studs에서 맞았다는 실험 기록이 아닙니다.
nil은 해당 호출 조건에서 결과를 받지 못했다는 관찰로 남깁니다. 길이가 짧거나 필터가 제외했을 수 있고, Streaming을 쓰는 클라이언트에 대상이 없을 수도 있습니다. 멀리 보이는 저해상도 표현만으로 조회 가능한 Part가 있다고 판단하지 않습니다. Streaming 문제는 모델 표시·Atomic 점검 글과 연결해 확인합니다.
진단용 생성 코드는 고정 좌표를 검사합니다. 보상·대미지 시스템을 완성하는 보안 코드가 아니므로 클라이언트가 보낸 ‘맞았다’는 값만으로 지급하지 않습니다. 서버의 요청 검증은 RemoteEvent 서버 검증 가이드에서 별도로 다룹니다.
6. 고쳐지지 않으면 이 기록으로 조건을 좁힙니다
실행 측: 서버 / 클라이언트
첫 오류 또는 Raycast 뒤 분기: 오류 / nil / 결과 있음
시작점 O: 목적지 T:
실제 direction: 길이:
Include·Exclude Instance와 자손 범위:
CanQuery·CanCollide·RespectCanCollide:
CollisionGroup·IgnoreWater:
결과 Instance·Position·Distance 또는 nil:
이번에 바꾼 한 가지: 되돌린 뒤 같은 결과인지:
각 줄을 채우기 어렵다면 그 항목을 ‘미확인’으로 남깁니다. 모르는 상태를 false로 바꾸거나 여러 설정을 동시에 껐다 켜지 않습니다. 고정 Part에서도 실패하면 먼저 객체 경로·실행 위치·첫 오류를 확인하고, 고정 Part는 되는데 원래 모델만 다르면 모델의 속성·필터·클라이언트 존재 범위를 좁힙니다. 협업자에게는 재현용 최소 조건과 로그를 전달하고 비공개 데이터·토큰은 포함하지 않습니다.
7. 출처·확인일·실행 한계
- Creator Hub: Raycasting — 목적지−시작점 계산, 필터와 Streaming의 적용 범위.
- WorldRoot.Raycast — 두 번째 인수의 길이 의미·15,000 studs 상한·반환 형식.
- RaycastParams — 현재 IncludeInstances·ExcludeInstances, nil과 빈 목록, RespectCanCollide 조건.
- BasePart.CanQuery — 공간 질의 포함과 CanCollide 조건.
- RaycastResult — 결과 Instance·Position·Distance 등의 속성.
확인일 2026-10-31. 현재 공식 원문과 API를 대조하고 좌표 산술 6가지를 별도로 검사했습니다. 실제 실행은 이 사이트의 브라우저 입력·방향·길이·생성 코드·오류 표시 범위입니다. Roblox Studio·Player의 실제 Raycast·충돌·필터·Streaming·서버 보안 판정과 Luau 자료형 검사는 실행하지 않았습니다. 좌표 표는 실측 맵이나 적중률·성능 결과가 아닙니다. 특정 프로젝트의 성공을 보장하지 않습니다.