Skip to content

Scene access and play camera

SDK 1.3 adds two things.

MemberWhat it does
host.SceneReads scene actors (cameras · paths · trigger zones · displays …).
host.ViewReads 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.

MemberTypeDescription
ActorsIReadOnlyList<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 = "{}");
FieldDescription
IdActor id (the name world logic uses)
KindKind (camera · path · trigger · blocker · display · text · spawn · light · sound …)
NameName shown in the Outliner
PosPosition (world coordinates, one block = 1)
Rot(yaw, pitch, roll) in Minecraft degrees
SizeBox size for trigger zones and blocker boxes; scale factor otherwise
PropsJsonProperty object as a JSON string. "{}" if none
  • This is the authored state, not the pose moved by animation during Play.
  • With many actors, Actors is heavy. Do not call it every time inside PlayTicked; read it once when Play starts.
  • Read PropsJson with System.Text.Json. For example: a camera’s fov, a path’s points (world coordinates [[x,y,z],…]).
ValueMeaning
yaw 0Looks toward +Z (south)
yaw 90Looks toward −X (west)
pitch 0Horizontal
pitch 90Looks 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") …
}
MemberTypeDescription
PlayingboolWhether Play or Simulate is running
PlayTimedoublePlay clock (seconds). Start = 0; stops while paused. 0 when not playing
CameraPosNpVec3Current camera position
CameraYaw · CameraPitchfloatCurrent camera angles (Minecraft degrees)
CameraFovfloatCurrent field of view (degrees)
SetCamera(NpVec3 pos, float yaw, float pitch, float fov = 0)boolMoves the camera to that position and direction. true on success
LookAt(NpVec3 target, float fov = 0)boolLooks at target from the current position (where this plugin last put it)
LookAt(NpVec3 eye, NpVec3 target, float fov = 0)boolLooks at target from eye
ReleaseCamera()voidReleases this plugin’s control of the camera (back to the original view)
PlayChangedevent Action<bool>?Play start (true) · end (false)
PlayTickedevent Action<double>?Every play clock tick (0.05 seconds). Value = elapsed seconds
RuleDetails
When it worksOnly during Play and Simulate. Otherwise it returns false and does nothing.
MovementOne call places the camera there. To move it, call it every tick in PlayTicked.
First-person bodyThe play body stops while you move the camera.
fov0 or less = keep the current field of view. Other values are clamped to 30 – 110 degrees.
Invalid valuesInfinite or NaN positions, and LookAt with the same eye and target, return false
RestoringReleaseCamera() · 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 controllersUses 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(); }
};
  • PlayTicked is called every 0.05 seconds. Keep it light.
  • The built-in action cinematic already does camera direction (cameras · paths · holds · moves). If you register the same type name with AddSceneEvent, it collides with the built-in and the plugin does not enable. For your own direction, do not register a type; use only Scene · 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.