씬 읽기와 플레이 카메라
SDK 1.3 은 두 가지를 더합니다.
| 멤버 | 하는 일 |
|---|---|
host.Scene | 씬 액터(카메라 · 경로 · 트리거 구역 · 표시 …)를 읽습니다. |
host.View | 플레이 상태와 시계를 읽고, 플레이 중에 뷰포트 카메라를 옮깁니다. |
이것으로 플레이 미리보기에서 카메라 연출(궤도 · 줌 · 경로 따라가기)을 만들 수 있습니다. plugin.json 에 "sdk": "^1.3" 을 씁니다. 에디터 0.9.1 이상이 필요합니다.
씬 액터: INpScene
섹션 제목: “씬 액터: INpScene”| 멤버 | 형식 | 설명 |
|---|---|---|
Actors | IReadOnlyList<NpSceneActor> | 씬 액터 전부(아웃라이너 순서). 부를 때마다 지금 월드에서 다시 읽은 사본입니다. |
Find(string id) | NpSceneActor? | id 로 찾기. 없으면 null |
public sealed record NpSceneActor(string Id, string Kind, string Name, NpVec3 Pos, NpVec3 Rot, NpVec3 Size, string PropsJson = "{}");| 칸 | 설명 |
|---|---|
Id | 액터 id(월드 로직이 쓰는 이름) |
Kind | 종류(camera · path · trigger · blocker · display · text · spawn · light · sound …) |
Name | 아웃라이너에 보이는 이름 |
Pos | 자리(월드 좌표, 블록 한 칸 = 1) |
Rot | (yaw, pitch, roll) 마인크래프트 도 |
Size | 트리거 구역 · 막는 상자면 상자 크기, 그 밖이면 크기 배율 |
PropsJson | 속성 객체 JSON 글. 없으면 "{}" |
- 저작한 모습입니다. 플레이 중 애니메이션으로 움직인 자세가 아닙니다.
- 액터가 많으면
Actors는 무겁습니다.PlayTicked안에서 매번 부르지 말고 플레이 시작 때 한 번 읽어 둡니다. PropsJson은System.Text.Json으로 읽습니다. 예: 카메라의fov, 경로의points(월드 좌표[[x,y,z],…]).
각도 규칙
섹션 제목: “각도 규칙”| 값 | 뜻 |
|---|---|
| yaw 0 | +Z(남쪽)를 봄 |
| yaw 90 | −X(서쪽)를 봄 |
| pitch 0 | 수평 |
| pitch 90 | 아래를 봄 |
마인크래프트 F3 화면의 각도와 같은 규칙입니다. NpSceneActor.Rot 와 INpView 의 각도가 같은 규칙을 씁니다.
foreach (var a in host.Scene.Actors) if (a.Kind == "camera") host.Log($"{a.Id} {a.Name} {a.Pos} yaw {a.Rot.X} pitch {a.Rot.Y}");
if (host.Scene.Find("route") is { } path){ using var doc = System.Text.Json.JsonDocument.Parse(path.PropsJson); // doc.RootElement.GetProperty("points") …}뷰포트 · 플레이: INpView
섹션 제목: “뷰포트 · 플레이: INpView”| 멤버 | 형식 | 설명 |
|---|---|---|
Playing | bool | 플레이 또는 시뮬레이트 중인지 |
PlayTime | double | 플레이 시계(초). 시작 = 0, 일시정지면 멈춤. 플레이 중이 아니면 0 |
CameraPos | NpVec3 | 지금 카메라 자리 |
CameraYaw · CameraPitch | float | 지금 카메라 각도(마인크래프트 도) |
CameraFov | float | 지금 시야각(도) |
SetCamera(NpVec3 pos, float yaw, float pitch, float fov = 0) | bool | 카메라를 그 자리 · 방향으로. 성공하면 true |
LookAt(NpVec3 target, float fov = 0) | bool | 지금 자리(이 플러그인이 마지막으로 둔 자리)에서 target 을 봄 |
LookAt(NpVec3 eye, NpVec3 target, float fov = 0) | bool | eye 에서 target 을 봄 |
ReleaseCamera() | void | 이 플러그인의 카메라 옮기기를 풂(원래 시점으로) |
PlayChanged | event Action<bool>? | 플레이 시작(true) · 끝(false) |
PlayTicked | event Action<double>? | 플레이 시계 한 틱(0.05초)마다. 값 = 흐른 초 |
카메라 옮기기 규칙
섹션 제목: “카메라 옮기기 규칙”| 규칙 | 내용 |
|---|---|
| 언제 되나 | 플레이 · 시뮬레이트 중에만. 아니면 false 를 돌려주고 아무 일도 없습니다. |
| 움직임 | 한 번 부르면 그 자리에 둡니다. 움직이려면 PlayTicked 에서 매 틱 부릅니다. |
| 1인칭 몸 | 카메라를 옮기는 동안 플레이 몸은 멈춥니다. |
fov | 0 이하 = 지금 시야각 그대로. 그 밖은 30 ~ 110 도로 맞춥니다. |
| 틀린 값 | 무한대 · NaN 자리, 눈과 목표가 같은 LookAt 은 false |
| 원래대로 | ReleaseCamera() · 플레이 정지(Esc) · 플러그인 끄기 · 격리 때 원래 시점(플레이 = 몸 눈 자리, 시뮬레이트 = 자유 카메라)과 시야각으로 돌아갑니다. |
| 여럿이 쥘 때 | 내장 동작 cinematic 미리보기와 같은 길을 씁니다. 같은 틱에 여럿이 옮기면 나중에 준 것이 이깁니다. |
예: 플레이 중 6초 궤도 카메라
섹션 제목: “예: 플레이 중 6초 궤도 카메라”콘솔에서 myorbit 를 입력하면 (0, 70, 0) 둘레를 6초 동안 돕니다.
double t = 0; bool on = false;
host.AddCommand(new NpCommand("myorbit", "myorbit", "플레이 중 6초 궤도 카메라", _ =>{ if (!host.View.Playing) return "먼저 플레이를 시작하세요"; on = true; t = 0; return "시작";}));
host.View.PlayChanged += playing => { if (!playing) on = false; };host.View.PlayTicked += dt =>{ if (!on) return; t += dt; var c = new NpVec3(0, 70, 0); var eye = new NpVec3(c.X + 30 * (float)Math.Cos(t), 85, c.Z + 30 * (float)Math.Sin(t)); host.View.LookAt(eye, c, fov: 60); if (t > 6) { on = false; host.View.ReleaseCamera(); }};예: 씬 카메라 액터로 줌
섹션 제목: “예: 씬 카메라 액터로 줌”host.View.PlayTicked += dt =>{ if (!_running) return; _t += dt; var cam = host.Scene.Find("cam_zoom_1"); if (cam == null) { _running = false; return; } host.View.SetCamera(cam.Pos, cam.Rot.X, cam.Rot.Y, fov: 70 - (float)_t * 5); // 시야각을 줄여 줌 if (_t > 6) { _running = false; host.View.ReleaseCamera(); }};팁 / 주의
섹션 제목: “팁 / 주의”PlayTicked는 0.05초마다 불립니다. 가볍게 씁니다.- 내장 동작
cinematic이 이미 카메라 연출(카메라들 · 경로 · 머묾 · 이동)을 합니다. 같은 type 이름을AddSceneEvent로 등록하면 내장과 겹쳐 플러그인이 켜지지 않습니다. 따로 연출하려면 type 은 등록하지 말고Scene·View만 씁니다. - 카메라 연출은 에디터 미리보기용입니다. 게임 서버의 카메라는 서버 플러그인이 맡습니다.
- 씬 액터를 만들거나 옮기는 API 는 아직 없습니다. 읽기만 됩니다.