Scene access and play camera
SDK 1.3 adds two things.
| Member | What it does |
|---|---|
host.Scene | Reads scene actors (cameras · paths · trigger zones · displays …). |
host.View | Reads the play state and clock, and moves the viewport camera during Play. |
With these you can build camera direction (orbit · zoom · following a path) in the Play preview. Write "sdk": "^1.3" in plugin.json. Editor 0.9.1 or later is required.
Scene actors: INpScene
Section titled “Scene actors: INpScene”| Member | Type | Description |
|---|---|---|
Actors | IReadOnlyList<NpSceneActor> | All scene actors (in Outliner order). Each call returns a copy freshly read from the current world. |
Find(string id) | NpSceneActor? | Find by id. null if not found |
public sealed record NpSceneActor(string Id, string Kind, string Name, NpVec3 Pos, NpVec3 Rot, NpVec3 Size, string PropsJson = "{}");| Field | Description |
|---|---|
Id | Actor id (the name world logic uses) |
Kind | Kind (camera · path · trigger · blocker · display · text · spawn · light · sound …) |
Name | Name shown in the Outliner |
Pos | Position (world coordinates, one block = 1) |
Rot | (yaw, pitch, roll) in Minecraft degrees |
Size | Box size for trigger zones and blocker boxes; scale factor otherwise |
PropsJson | Property object as a JSON string. "{}" if none |
- This is the authored state, not the pose moved by animation during Play.
- With many actors,
Actorsis heavy. Do not call it every time insidePlayTicked; read it once when Play starts. - Read
PropsJsonwithSystem.Text.Json. For example: a camera’sfov, a path’spoints(world coordinates[[x,y,z],…]).
Angle conventions
Section titled “Angle conventions”| Value | Meaning |
|---|---|
| yaw 0 | Looks toward +Z (south) |
| yaw 90 | Looks toward −X (west) |
| pitch 0 | Horizontal |
| pitch 90 | Looks down |
These are the same conventions as the angles on the Minecraft F3 screen. NpSceneActor.Rot and the angles in INpView use the same conventions.
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") …}Viewport · Play: INpView
Section titled “Viewport · Play: INpView”| Member | Type | Description |
|---|---|---|
Playing | bool | Whether Play or Simulate is running |
PlayTime | double | Play clock (seconds). Start = 0; stops while paused. 0 when not playing |
CameraPos | NpVec3 | Current camera position |
CameraYaw · CameraPitch | float | Current camera angles (Minecraft degrees) |
CameraFov | float | Current field of view (degrees) |
SetCamera(NpVec3 pos, float yaw, float pitch, float fov = 0) | bool | Moves the camera to that position and direction. true on success |
LookAt(NpVec3 target, float fov = 0) | bool | Looks at target from the current position (where this plugin last put it) |
LookAt(NpVec3 eye, NpVec3 target, float fov = 0) | bool | Looks at target from eye |
ReleaseCamera() | void | Releases this plugin’s control of the camera (back to the original view) |
PlayChanged | event Action<bool>? | Play start (true) · end (false) |
PlayTicked | event Action<double>? | Every play clock tick (0.05 seconds). Value = elapsed seconds |
Camera control rules
Section titled “Camera control rules”| Rule | Details |
|---|---|
| When it works | Only during Play and Simulate. Otherwise it returns false and does nothing. |
| Movement | One call places the camera there. To move it, call it every tick in PlayTicked. |
| First-person body | The play body stops while you move the camera. |
fov | 0 or less = keep the current field of view. Other values are clamped to 30 – 110 degrees. |
| Invalid values | Infinite or NaN positions, and LookAt with the same eye and target, return false |
| Restoring | ReleaseCamera() · stopping Play (Esc) · disabling the plugin · isolation return the camera to the original view (Play = the body’s eye position, Simulate = free camera) and field of view. |
| Multiple controllers | Uses the same path as the built-in action cinematic preview. If several move it in the same tick, the last one wins. |
Example: a 6-second orbit camera during Play
Section titled “Example: a 6-second orbit camera during Play”Enter myorbit in the console to orbit around (0, 70, 0) for 6 seconds.
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(); }};Example: zooming with a scene camera actor
Section titled “Example: zooming with a scene camera actor”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); // zoom by narrowing the field of view if (_t > 6) { _running = false; host.View.ReleaseCamera(); }};Tips / cautions
Section titled “Tips / cautions”PlayTickedis called every 0.05 seconds. Keep it light.- The built-in action
cinematicalready does camera direction (cameras · paths · holds · moves). If you register the same type name withAddSceneEvent, it collides with the built-in and the plugin does not enable. For your own direction, do not register a type; use onlyScene·View. - Camera direction is for the editor preview. The game server’s camera is handled by the server plugin.
- There is no API yet for creating or moving scene actors. Read-only access only.