Skip to content

Players and movement

Entity → Characters → Platformer Player makes a player that runs and jumps straight away: its Platformer Movement runs at Speed, gets up to it and stops at its Acceleration and Deceleration (less of both in the air, by Air Control), and jumps Jump Height high with the Jump action. Jumps are forgiving: one pressed a moment before landing (Jump Buffer) or a moment after running off a ledge (Coyote Time) still happens, and letting go early makes a short hop. Falling is a little heavier than rising (Fall Multiplier), up to Max Fall Speed. Tick what the game needs: Air Jumps (1 is a double jump), Wall Slide and Wall Jump, and Dash (the Dash action, Shift or the gamepad’s B: Dash Speed for Dash Time, once in the air until landing). Down and Jump on a one-way platform drops through it. It flips its sprite to face where it’s going, plays sounds and a Dust Effect if you give it some, and if it has an Animation with clips named Idle, Run, Jump, Fall, Climb, Dash or WallSlide, it plays them itself. Entity → Characters → Top-down Player makes one with Top-down Movement instead: eight directions (or Four Way), an optional dash, and Idle/Run clips (with IdleUp, RunDown and so on, facing that way). It ignores gravity. Entity → Characters → Grid Player makes one with Grid Movement, for puzzle games, roguelikes and old-school RPGs: each press steps it one cell of the scene’s tilemap (or the one its Map names), gliding there in Step Time seconds, and holding a way keeps it walking (after Repeat Delay seconds, or untick Repeat to step once a press); a press during a step is taken when it ends. Solid tiles, solid colliders and other grid movers block it, and it turns to face them instead, playing its Bump Sound once a press; triggers (coins, doors), one-way and background tiles don’t, and layers its collider ignores don’t either. It starts on the middle of the cell it’s placed in, moves four ways (the way pressed last wins) or Diagonally too (never cutting a wall’s corner), stays on the map unless Stay On Map is unticked, and plays Idle and Walk (or Run) clips, with IdleUp, WalkDown and so on. With no tilemap it steps a world unit at a time, between whole-number positions. Untick Controllable for a cutscene. When a player is selected, the Scene view draws how far it jumps each way.

A Grid Movement can be sent somewhere and walk there by itself, a cell at a time: workers to a free spot by a machine, villagers home, a unit to where it was clicked. Its Destination (under Walking) says where: cells as “column row” pairs counted as its Cell is (row 0 at the top), separated by semicolons, e.g. 4 2; 5 2, of which it heads for the nearest that’s free; or an entity’s name, whose cell it walks onto, or next to when something solid or another grid mover is there. Type one in, set it from a trigger or a button with its Walk To action, or call WalkTo from a script (WalkTo([(4, 2), (5, 2)]), WalkTo((4, 2)), WalkTo(entity)). It goes the shortest way, four ways or eight if it’s Diagonal, round solid tiles, solid colliders (only those on its Blocking Layers, e.g. Obstacle, when it has any: they’re then the only colliders that stop its steps too), a solid Conveyor’s belts (it crosses at their crossings, see Conveyors) and the cells other grid movers are in or stepping into. It plans again at every cell, so it finds a new way round anything put down in front of it. A step of the game longer than its Step Time (a high Time.Scale) takes every cell it covers, each checked and planned as at normal speed, round corners too, so a walk costs the same game time at any speed; a press is still one cell.

When another mover is in the way and there’s no way round, it waits for it (its Blocked event and Blocked Message, once each time; Is Waiting is true meanwhile) and carries on as soon as it can. Two walkers that meet head on in a one-cell aisle wait Give Way seconds, then one steps aside to the nearest free cell off the other’s way (the one later in the scene, unless only the other has somewhere to go), lets it by and goes on. On getting there its Destination empties and it raises Arrived with the cell (and sends its Arrived Message). Stop Walking, or a way pressed for a player, ends a walk where it is. A walk is worked out where the game is run, the same way every time, so a rewind or a network game sees the same walk. To plan without walking, a script asks the tilemap: FindSteps(start, goals, avoid, blockingLayers) gives every cell of the way to the nearest goal (see Scripting).

Everything that reads the keys, the mouse or the gamepad has a Controllable tick: the movements (platformer, top-down, grid and first person), match-3 and falling-block boards, the strategy Commander, the Tactics Controls, a card game’s Hand, a visual novel’s Stage (its Advance, Skip and Auto actions), a rhythm game’s Note Lanes and Song Select, an adventure’s Walker, a fighting game’s Fighting Character and Character Select, pinball’s Flipper, Plunger and Tilt, a Slingshot, the Sandbox Tools, a Block Builder (its hotbar and crafting go with it) and an RPG Battler (its attack, spell and item keys). A few things go by another’s: a first-person Weapon fires while its player’s movement has the input, and a Move History hears Undo while a grid player it covers has it. Unticked, it ignores the player while the rest of it plays on: a board still clears and falls, a character still falls and lands. Each has a Focus action, which a trigger, a wire or a script (Game.Focus(entity)) does to hand it the input: it ticks Controllable on that entity and whatever is inside it, and unticks it on everything else the same player plays. A platformer’s arcade cabinet focuses its match-3 board as the player walks up to it (“when Play arrives, Focus the Board”), and the board’s Won message focuses the player again. A character that has given up the input doesn’t work doors, switches or dialogue with Interact either. A script’s own component joins in by marking its true-or-false property [Focus], or, to go by another’s, the class [FocusFrom(typeof(PlatformerMovement))]. In a network game the host says who has focus, and a player’s own character gives it up only to what that player (or everyone) plays. See Mixing genres.

Two people can play at one computer, each with their own character: give each a Played By naming Player 1 or 2 (up to 4). What reads the controls on it (its movement, attack, a fighter’s moves, everything that uses Game.InputOf) then reads that player’s alone, and everything without one (menus, pause, buttons) answers to everyone. The keys and controllers are shared out by how many play (the most a scene’s Played Bys name) and how many controllers are plugged in:

Controllers Player 1 Player 2
None the left keys: WASD to move, F and G for the first two buttons (Punch and Kick, Fire and Attack), Space to jump, Left Shift to dash, E to interact the right keys: the arrows to move, K and L (or the number pad’s 1 and 2), Right Ctrl (or the number pad’s 0) to jump, Right Shift to dash, Enter to interact
One the whole keyboard and the mouse the controller
Two the keyboard, the mouse and the first controller the second controller

An action without keys of its own on a side keeps its own keys on that side of the keyboard (Undo is Z on the left, U on the right); a controller’s buttons are its own player’s. With three or four playing, the keyboard and the controllers go round the same way: one controller short of one each, the first player has the keyboard; fewer, the first two split it. With one player in the scene, that player has every key and controller, as without a Played By. A game can let players choose (Game.LocalPlayers.Choose(2, PlayerDevice.Gamepad1)) or swap the first two (Swap(1, 2, playing), a fighting game’s Swap Controls button); their choice is kept with their settings, and Describe says what each plays with (“Left keys (WASD)”, “Gamepad 2”). Focus is each player’s own: a Focus action given to Player 1’s board leaves Player 2’s character as it is.

Controllers are read apart, up to four (on Windows through XInput, in a browser through its Gamepad API), each player’s own shaking alone when it rumbles; the game by itself (menus, a single player) reads every one at once. Agents play a second player’s controller with game_input names like "Gamepad2 X" and "Gamepad2 Left".

Ladders, crates, springs and crumbling ledges

Section titled “Ladders, crates, springs and crumbling ledges”

Entity → Level → Ladder makes a ladder (a trigger with a Ladder); up and down climb it without gravity, and Jump leaves it. Put a one-way platform at the top to stand on: climbing passes through it both ways, so down from the top climbs back down. Entity → Physics → Crate makes a crate with a Pushable: players walk into it to push it at its Speed (0.6 of theirs), along the ground in a platformer and any way in a top-down game, and it pushes crates in front of it until a wall stops them. It’s on the Crate layer, so a pressure plate with Crate in its Layers can wait for it. In a scene with grid movers it’s a grid crate instead (see Sokoban crates and goals). Entity → Physics → Spring makes a spring: a Bouncer sends whatever lands on it flying at its Strength in its Direction (sideways makes a bumper; on a trigger it’s a boost pad), giving a player its air jumps and dash back, and the Scene view draws where it sends things. Add a Crumble to a platform and once the player stands on it, it shakes for Delay seconds, falls away and comes back Respawn seconds later, once nobody’s in the way.

Tick a Body’s Rotates and it turns: a crate landing on its corner tips over and falls flat, a plank hanging over a ledge tips off it, a ball thrown at the top of a tall plank knocks it over, and its box collider turns with the entity (the Scene view draws it turned). Spin is how fast it turns (degrees a second, anticlockwise; set it to start it spinning), Grip how well it grips what it touches (0 slides off an edge like ice, 1 hardly slips, so it tips over instead), and Mass with its collider’s size how hard it is to turn. Everything else meets it as it’s turned: rays and overlaps, shadows, a player who walks into a crate shoves it along and one who runs into a plank’s end tips it, a weight dropped on one end of a seesaw lowers it, and a player walks up a tilted plank like a ramp (a turned, Frozen box is a ramp or a tilted wall that stays put). It lands on tilemaps, slopes and one-way platforms, meets a hex map’s hexagons with its turned box, and on an isometric map meets the walls with the diamond under it, as everything does there. Bodies that don’t rotate (the default) stay upright whatever hits them, as players and enemies should, and every existing scene and template works as it did. Welded into a contraption, bodies are one body that turns when all of them rotate (see Contraptions and wiring).

Bodies that rotate are worked out together: every one touching another, and what they touch, in one go, in quarter steps, each starting from how hard every point pushed in the quarter before (and the first from the step before, which the scene remembers), so a tower’s weight is carried all the way down to the floor from the start; the two corners of a crate lying flat on another are pushed together, so it lands straight and neither rocks nor creeps, and overlaps are eased apart rather than kicked. Towers of ten crates and pyramids of fifty-five (or two hundred and ten) stand, falling asleep within a second or two, crates stacked a little off true settle without toppling, and crates dropped in a heap settle, on colliders, tile floors, slopes and hex maps alike (a jumbled heap of sixty in a bin sleeps within two seconds: one wedged between a slant below it and a side a little above its middle still counts as held up). Bodies touching fall asleep together while any of them is moving; once they’re all as good as still, each falls asleep after half a second still by itself, so a deep heap sleeps a part at a time rather than waiting for every crate in it to be still at once (two hundred jumbled crates in a bin sleep within four seconds). A body moving into a sleeper wakes it; one that’s all but still leans on it as on something that holds still. Once a pile has stayed still for half a second it falls Asleep: it stays exactly where it is and costs a fraction of what it did (each step it only checks it still has something under it) until something disturbs it: a hit, a push or a spin from a script, a player walking into it, something pushed into it, or what it rests on moving or being taken away. Then it wakes, and so does everything moving it touches; taking out or turning off something beside it, or clearing tiles under it, wakes it too, so a crate held up by one that’s gone falls. Someone walking into a tower leans on it (a crate rocking into their side doesn’t lift them on top of it), and a pile shoved against someone standing still settles and sleeps there. Still For counts how long it’s been still. Tick Asleep to start a pile asleep, so a tower built resting on itself stands untouched until something hits it (a crate set asleep in the air isn’t held up by anything, so it wakes and falls). Sleep is saved with the scene, and how hard each point pushed is kept with it (rewind snapshots keep it too), so a rewind, or the same game played twice, ends the same to the last bit; in a network game the host works it out and players see it as it is. A pyramid of 55 crates and a tower of 10 cost about 0.3 ms a physics step while they’re awake and 0.14 ms asleep; a pyramid of 210, 1.2 and 0.5 ms; none of it makes garbage, and BunnyMark is as fast as before (dotnet run -c Release tools\stackbench.cs -- --rows 10 --tower times them on your computer). Ten sleeping towers of posts and planks, 150 bodies, knocked down by a heavy ball cost about half a millisecond a step as they collapse, and make no garbage either: a scene’s first step makes room for every body in it that turns to be awake and touching what’s round it at once, so nothing grows as a pile wakes and comes down (--breakable 150 --sturdy).

A body with a Circle Collider that Rotates is a ball, and it rolls. On flat ground, down slopes (a tilted Frozen box, or slope tiles), over tile floors and hex floors it rolls without slipping: its spin keeps pace with how fast it goes, so its sprite turns just as far as it has rolled (a ball of radius 0.5 turns a full circle every 3.14 units). Set going without spin, it skids at first and its Grip soon has it rolling, at two thirds of the speed it skidded at, as a real ball does. Rolling Resistance brings it to rest: 0 rolls on and on, 0.1 (the default) stops a ball rolling at 5 units a second in about 3 seconds and 7.5 units, and a ball rests on a slope gentler than its rolling resistance (rise over run) and rolls down a steeper one. Friction slows only its sliding, so it turns a skid into rolling and leaves rolling alone. Its spin goes into its bounces: one dropped spinning bounces off the way its spin carries it (topspin forwards, backspin back), one thrown along lands spinning, and a bouncy one rolling into a wall bounces back off it. Rolling over where two boxes, platforms or tile runs meet end to end it doesn’t catch on the next one’s corner. Balls roll up against crates and walls and rest there, heap up in a bin, stand stacked two with one on top, and fall asleep like any pile (a heap of two hundred dropped in a bin within three seconds); a pile that wakes picks up from how hard its balls pushed when they fell asleep, so it doesn’t sag.

A player walking into a ball pushes it along ahead of them and it rolls on when they stop; running into it harder kicks it further. From a script, set its Velocity (a kick: it skids, then rolls) or push it off its middle with PushAt to put spin on it (under its middle for backspin, over it for topspin). In a top-down game (its Gravity Scale 0, on an isometric map or anywhere else) it rolls on the ground under the view: rolling resistance slows it just the same, and its spin (from a glancing hit) dies away too, but its sprite only turns with that spin, since a picture turned on the screen can’t show a ball rolling away from you. Give something floating in space a rolling resistance of 0 and it drifts on. A heap of 60 balls costs about 0.14 ms a physics step awake and 0.06 ms asleep, 200 balls 0.5 and 0.23 ms, with no garbage (dotnet run -c Release tools\stackbench.cs -- --balls 60). The Contraption template’s Ball rolls.

A Polygon Collider is a shape with straight sides between its Points: a ramp, a wedge, a rock, a hill, a boat’s hull, a cup. Its points are “x y” pairs separated by semicolons, in its own units round the entity (plus its Offset, and grown with the entity’s scale): -1 0; 1 0; 0 1 is a triangle two wide and one tall, and they can go round either way. Select it and the Scene view puts a knob on each point and a plus halfway along each side: drag a knob to move its point, drag a plus to add one there, double-click a knob to take its point off (it keeps three). Hold Ctrl to snap to half units. Each drag is one undo step, and clicking inside a polygon with nothing drawn there selects it. An adventure’s walk areas and hotspots are edited the same way (see Point-and-click adventures). Entity → Fit Polygon Collider to Sprite traces round the solid part of the selected entity’s sprite (the frame it shows, its biggest blob with any holes filled in) and makes that its points, up to twelve that hug it without crossing, in place of its box or circle collider (keeping whether it’s a trigger and its layers); tidy it up by dragging the points.

A convex shape is one piece; a concave one (an L, a cup, a crescent) is split into convex pieces by itself, which the Scene view shows as faint lines inside it, and it collides as the shape it is: a ball dropped into a cup rolls to its floor and stays in it, and something sliding over a join between two pieces doesn’t catch on it. Points that don’t make a proper shape never stop anything working: they’re fixed up and the Inspector says what was wrong above its fields (agents see the same note). Fewer than three points make a square one unit across (round the one point, if it has one), two points or points all in a line a bar a tenth of a unit thick along them, sides that cross the shape round all the points, and a point that doubles back on itself along a side is left out; the Scene view draws such a shape in red as it’s fixed up, with the points as they’re written dashed over it. Only the first 64 points count.

Like a box, it stays upright whatever the entity’s rotation unless its Body Rotates: then it turns with the entity round where it balances (its WorldCentroid, worked out from its area, so a triangle turns round its middle third of the way up), and its mass is spread over its area, so a long thin shape turns slowly. It tips over onto a side and rests there, rolls end over end down a slope if it’s round enough (an octagon rolls down a ramp and comes to rest flat on the floor), stacks (a tower of hexagons stands), heaps up in a bin with crates and balls and falls asleep with them, and lands on tile floors, slope tiles and hex floors, and, on an isometric map, meets the walls with the diamond under it, as everything does there. A body that doesn’t rotate can have one too, staying upright, and a static one (with no body) is a wall or a hill: a player walks up and down its slant as they do a tilted plank, and lands on it where it is rather than on the box round it. Everything else meets it as the shape it is: rays (Game.Physics.Raycast hits its sides, never a join inside it), overlaps, triggers (a polygon trigger tells what comes into it), shadows (from each side) and grid movers (a cell whose middle it covers is a wall). Rewinds and network games play it out the same to the last bit, and it makes no garbage a step. A heap of 60 polygons (triangles, pentagons, hexagons and concave Ls) in a bin costs about 0.23 ms a physics step awake and 0.15 ms asleep, and falls asleep within two seconds (two hundred take about nine) (dotnet run -c Release tools\stackbench.cs -- --shapes 60).

A Hinge Joint pins its body to another (To, by name) or, with To empty, to a point in the world, at its Anchor (in its own units from its position: (0, 0) is its middle, as a wheel’s; (-2, 0) one end of a plank four long, as a door’s), and it turns there: a wheel on a cart, a door, a flipper, a seesaw, a windmill, a chain of links. Entity → Add Hinge hinges the selection at its middle, to the world, or with two selected, to the one picked first (pick the cart, then Ctrl+click the wheel), ticking its body’s Rotates. The Scene view draws a pin where every hinge is, and on the selection puts a knob on its anchor to drag (Ctrl snaps to half units) and, with Limit ticked, a wedge it swings through with a knob on each end to drag its Lower Angle and Upper Angle (whole degrees; Ctrl snaps to fifteen), each drag one undo step (double-click an end to untick Limit). The two are joined as they stand when the game starts (Joined, with the Other Anchor and Start Angle the game works out; untick it to join them again where they are), so its angles count from how they’re placed, from -180 to 180, and Angle says how far it has turned (an output, so a wire can read it).

Limit keeps it between its two angles (a door that opens one way, a flipper’s travel). Motor turns it at Motor Speed (degrees a second, anticlockwise) as hard as Motor Strength lets it (a torque: a heavy load turns it slowly or stalls it); a switch or a wire into its Power turns the motor on and off (a flipper on a button), and its Reverse action turns it the other way. Friction (0.05 by default) makes it stiff, the more so the more weight hangs on it: 0 swings on and on, 1 stops a swinging door soon (a little off straight down). The two it joins don’t bump into each other unless Collide is ticked. What it’s hinged to turns with it if that rotates too, and is pulled about by it if it moves with physics (a body that rotates, a welded contraption, one hung on a hinge itself); anything else, a player, a wall, a platform moved by a script, just carries the hinge along. A body that doesn’t rotate hangs upright from its hinge, as a Ferris wheel’s seats do.

Hinges are worked out with the bodies that turn, in the same quarter steps and before their contacts, each starting from how hard it pulled the step before (kept with the scene, so a rewind or a network game plays them out the same to the last bit), and a hinge holds its two together to about a thousandth of a unit. Hinged bodies fall asleep together when they’ve been still a while (one hanging from a hinge counts as held up), but not while a motor runs. Twelve chains of five links cost about 0.1 ms a physics step swinging, with no garbage (dotnet run -c Release tools\stackbench.cs -- --hinges 60; --welded 60 heaps welded pairs).

A Rope ties its entity (at its Anchor, in its own units from its position: (0, 0.5) is the top of a crate one high) to another (To, by name, at its Other Anchor in that one’s own units) or, with To empty, to a point in the world (Other Anchor is then where in the world). Tick Loose End to leave that end hanging free instead, starting out towards Other Anchor (and on straight down for whatever length is left): a rope to climb and swing on, a bell pull. Its Length is how long it is (0: as far apart as its ends are as the game starts); the ends can come closer, and it sags, but no further apart. Either end can be a body, pulled about by it (and turned, if it rotates: a crate hung by its corner turns to hang corner up and rocks about), something that doesn’t move, or the world; a balloon tied to a crate floats up to the end of its rope and lifts a light one. A body that doesn’t rotate hangs upright from it. Changing Length while the game runs winches what hangs on it up and down.

Entity → Add Rope ties a rope to the selection: with two selected, from the middle of the one picked last to the middle of the one picked first, a little longer than they’re apart; one with a body, hanging from a hook in the world three above its top; one without (a ceiling, a branch), hanging loose three down from its bottom. The Scene view draws it hanging as it will at rest, a ring at each tied end, and on the selection a knob at each end to drag (its start in its entity’s own units, its other end in the own units of what it’s tied to, or in the world) and one at its middle for its Length: drag it down to make it longer, up to shorten it (Ctrl snaps to half units); double-click it for as long as its ends are apart. Each drag is one undo step.

It hangs and sags under gravity (Gravity Scale: 0 in a top-down game, where it lies where it’s put), swings, and comes to rest. With Collide ticked (the default) it meets the world, as thick as it’s drawn (Width, at least 0.08): it lies on the ground, drapes over boxes, crates and tile floors, slopes and hex walls, and wraps round corners, so a crate swinging on it round a peg hangs from the peg and swings round it. It doesn’t push what it lies on (it weighs next to nothing), and it hangs in front of players rather than meeting them, for them to grab. Stiffness (1, the default) doesn’t stretch; lower stretches like elastic, so what hangs on it bounces: at 0.5 a bungee cord (a crate stretches it about 0.3), at 0 a rubber band. It’s drawn as a smooth curve in its Color.

Climbable (on by default): a player with Platformer Movement grabs it with up where its hands meet it (in the air too), hangs on it, climbs up and down it at its Climb Speed (never into what it’s tied to; off the bottom of a loose end, it lets go), swings on it left and right, and jumps off it with Jump, keeping its swing (holding down, it just lets go). Is On Rope says it’s on one, and it plays its Climb clip. Its weight hangs on the rope, so a rope between two posts sags under it.

Break Force (0, never) is how hard it can be pulled before it snaps, in the units of gravity’s pull (a crate of Mass 1 hanging still pulls 25); its Tension output says how hard it’s pulled now. Snapped (or Cut, an action a wire or script can call), its two halves hang from their ends, Broke turns on (an output: wire it to a lamp or a gate; untick it, or call Mend, to join it up again) and it sends its Break Message, with the entity as its data.

Ropes are worked out with the bodies that turn, in the same quarter steps as contacts and hinges, as a chain of short pieces (one about every quarter unit, up to 48), each held its length apart and every point held within the rope’s length of a tied end so it doesn’t stretch under its own weight, while what hangs on it is held no further from what holds it up than the rope between them. A rope still a while falls asleep until something moves near it, its ends move, someone grabs it, or it’s cut. Everything it knows (its points, how fast they go, how hard each piece pulls, who hangs on it) is kept with the scene, so a rewind plays it out the same to the last bit; in a network game the host swings ropes and what hangs on them, and each player’s machine hangs its own copy of each rope between where the host has its ends (a player climbs on their own machine). Forty ropes swinging over pegs, half with crates on, cost about half a millisecond a physics step, with no garbage (dotnet run -c Release tools\stackbench.cs -- --ropes 40).

Add a Follow to the camera and set its Target (Player) and it follows with no code. Smoothing sets how quickly it catches up (0 sticks exactly), Offset shifts the view (say 0, 2 to see more above the hero), Dead Zone is a box the target can move about in without the camera moving (a tall one keeps a platformer’s camera still through jumps), and Look Ahead leads the way the target is moving. Set Stay Inside to the name of the level’s tilemap, a big box collider or a backdrop sprite, and the camera never shows past its edges. Follow works on anything, not just cameras: a pet that trails its owner. For top-down games, tick the camera’s Sort By Y so whatever is lower on screen draws in front. A sprite sorts by the bottom of its picture, where it stands, so a tall tree and the hero beside it sort by their feet. Something made of several sprites (a pallet with a stack of crates on it, a machine with its operator, a truck with a label) gets a Sort Group on its root: everything inside it then sorts as one at the root’s feet, so the hero walks in front of the whole stack and behind all of it rather than between its crates. Inside the group, the parts draw by their own Order, then in Hierarchy order. Ground Offset moves the point it sorts at up (or down, below 0) from the root’s feet, for a root whose picture has space under where it stands or one that draws nothing (it then sorts at its position).

For a management, building or strategy game, add Camera Controls to the camera instead and the player pans and zooms with no code: the keys (or a controller’s stick) pan at Pan Speed screen heights a second, the middle or right mouse button drags the world along (Drag Button), and the mouse wheel zooms toward the mouse, each notch by Zoom Step, between Zoom Min and Zoom Max (the camera’s Size). The keys are the built-in PanUp, PanDown, PanLeft and PanRight actions (WASD, the arrows and the D-pad), so Game → Controls rebinds them like Jump, players change them with Rebind buttons or Input.Rebind("PanUp", Key.I), and taking W and S off them frees those keys for the game; untick Pan With Keys to pan with the mouse alone. Tick Edge Scroll to pan when the mouse rests at the screen’s edge. Stay Inside names a tilemap, box collider or sprite the view never goes past, read each frame, so a level that grows lets the view reach further. The wheel, drags and the screen’s edges belong to the HUD while the mouse is over it (a button, an open panel, or a sprite pinned with a Screen Anchor), it works while the game is paused but not under a pause menu, and setting the camera’s Hud Size keeps the HUD the same size as it zooms (see Menus, HUDs and pickups). A drag holds the world point it took hold of under the mouse on any screen and at any game speed, a step at a time (fast-forwarded too), and dragged past a Stay Inside edge it takes hold where the view stopped, so dragging back moves it at once. Scripts read IsDragging, and change the camera’s Size and position as ever; a script of its own that moves the camera by the mouse goes by Input.MouseOnScreen (where the mouse is on the view, -1 to 1 each way) and the camera as it is, as these do, since Input.MouseWorld is found through the camera as it was last drawn, a step behind while it moves.

For a “look at this” moment (a guided tour, a cutscene, a building just finished), a script can take the camera over: Game.Find("Main Camera")?.GetComponent<CameraControls>()?.FocusOn(worker, 6) glides to the worker over Focus Seconds (0.75 by default), zooming to Size 6 as it goes, then keeps the worker in the middle of the view as it walks, inside Stay Inside, while the player’s keys, drag and wheel wait. Without a Size it zooms to Focus Size (or keeps its own, with that at 0); FocusOn(new Vector2(12, 4)) looks at a point instead, and focusing on the next stop while focused glides on from there. Release() hands the camera back where it is: it zooms back out to the Size it had before the first FocusOn, over the same time, and then the player pans and zooms as before. IsFocused and FocusTarget say what it’s doing. A Trigger, or a Button whose Action is Do, can do Focus On (with the entity’s name) and Release too, so a tour needs no code. To jump the view and give it straight back (a hotkey to the selected worker, the dock, a control group), GlideTo(target) (an entity or a point, with an optional Size and seconds) is a FocusOn that ends on arrival: it keeps the camera’s Size unless given one, there is no Release, and the keys work again the moment it arrives. A pan key, a drag or the wheel during the glide cancels it where the camera is, and a Button or Trigger can do Glide To with the entity’s name. IsGliding says one is under way.

The player can choose how the camera pans in an options menu: a Toggle whose Setting is EdgeScroll turns the screen’s edges panning off or on for every Camera Controls (it shows the camera’s own Edge Scroll until the player chooses, and then their choice wins), and a Slider set to PanSpeed (say 0.5 to 2, in steps of 0.25, with a text showing {0:0.00}x) multiplies the keys’ and the edges’ Pan Speed. Both are remembered, kept through a New Game, and are Game.EdgeScroll (a bool?, null until chosen) and Game.PanSpeed (1 by default, which changes nothing) for scripts.

A management or strategy game where the player steers workers, machines or trucks with the mouse needs no code to select them. Add Selection Controls to the camera and a Selectable to each thing that can be selected (on its prefab). A click picks the one under the mouse (the one drawn on top where several overlap) and a click on nothing clears; a left-drag on the world draws a box and picks the selectables inside it; holding Shift adds what’s clicked or boxed to the selection, or takes a clicked one out of it; and a double-click picks every one of that kind on screen. Ctrl and a number (1 to 9) keeps the selection as that control group, the number alone picks it again (with Shift, adds it), and pressing the number twice quickly moves the camera to the middle of the group. Esc clears the selection: while something is selected it claims Back, so Esc clears the selection rather than opening the game menu, but a window open over the game (a panel that doesn’t pause it) closes first, and the next Esc clears. A marker is drawn round each thing selected (an outline in Marker Color, or a Marker Image stretched round its area, nine-sliced with Marker Slice like a sprite’s Slice, Marker Padding out from it), and while dragging, the box (Box Color, or a Box Image).

A Selectable’s Kind (Worker, Smelter; empty goes by the entity’s name) is what a double-click picks all of. Untick In Box for what’s picked one at a time, a machine or a stack, so a box drawn over a crowd picks only the workers in it; untick Clickable for something that’s only a target (a resource, an enemy). Its area is its Size (centered on it, plus Offset), or with none its Button’s, box collider’s or sprite’s; it turns and scales with the entity, so a truck parked at 90 degrees is clicked, boxed (a turned rectangle against the box) and marked as it lies.

A right-click on the world with something selected is a command, which the game carries out itself: the Selection Controls’ Commanded event says what was under the mouse (the selectable on top, one that isn’t Clickable too, or a button in the world; null for the ground), the point in the world and what’s selected, and a script sends them there, to the machine or to unload the truck. The press is the command’s, so it doesn’t also drag the camera; with Camera Controls set the camera’s Drag Button to Middle and keep the right button for commands.

Its keys are built-in input actions, so Game → Controls rebinds them, players change them with Rebind buttons, and a Controls List shows them: Select (left click), Command (right click), AddToSelection (Shift), AssignGroup (Ctrl, held) and Group1 to Group9 (the number keys). Double Click Seconds is how quickly a second click (or a group’s second press) has to come. Clicks on a pop-up or anything pinned to the screen (a HUD button) don’t select, and neither does a click on a button in the world that has no Selectable. A button on a Selectable, or inside one (a worker’s own Figure Button), doesn’t stop it being selected: the click selects it and the button’s click fires as well, so one click can do both and the button needs no Selectable of its own. While the mouse is busy with something else, a building tool in hand or a road being painted, set its Busy from the script (or name a Busy Flag that a trigger or Game.SetFlag sets): it then leaves the mouse and Esc alone, so the game’s own left-drag paints. A Line Tool in hand (its Controllable ticked) makes it busy by itself. Untick Controllable (or Focus something else) and it ignores the player while the selection stays.

Scripts read Selected (and SelectedCount, an output a Counter or Text shows), hear SelectionChanged, and call Select(entity), Add, Remove, Clear(), Group(n) and SetGroup(n, entities); a Selectable has IsSelected and Selected and Deselected events. What’s destroyed or hidden drops out of the selection. The selection is each machine’s own: in a network game, send the orders a command gives as you would any other. The strategy Commander (see Real-time strategy) selects by the same rules and the same actions, with its own HUD, orders and team.

A camera with a Viewport draws into part of the screen, over the main view: a minimap in a corner, each player’s half of a split screen, or a window looking through someone’s eyes in a 2D game. Left, Top, Width and Height place it, as fractions of the screen from its top left (0, 0, 0.5, 1 is the left half), so it keeps its place at any window size; the camera’s Size is half the view’s height, and its width follows the part’s shape. Order says which goes on top where views overlap, Border frames it (transparent for none), and Shown hides it (a switch or wire powers it, for a map shown while a lever is on). The main view is the first camera without a viewport. Anything riding inside a viewport’s camera (its children) is that view’s own HUD; the main view’s HUD (anything with a Screen Anchor, or inside the main camera), menus and fades stay on top of every view. A Follow on a viewport’s camera keeps its own view inside Stay Inside. Give a viewport’s camera a First Person View and that window shows the game through the viewer’s eyes while the rest of the screen stays 2D (it leaves the mouse to the 2D game). Viewports only draw, so rewinds and network games are as ever, and they’re drawn the same on the desktop and in the browser. In a script, Game.MouseIn(camera, out var world) says whether the mouse is over a camera’s part of the screen and where in the world that is through it (for clicking on a minimap), and Game.AspectOf(camera) the shape it’s drawn at.