# PickOptions

> Talos next · Since 0.6

Options for {@link WorldQuery.pick}.

## Signature

```ts
export interface PickOptions {
  /** Sweep a sphere of this radius instead of a thin ray, metres — easier to aim at something small. Default 0. */
  radius?: number
  /** Whether a trigger volume stops the pick. Default **false**, unlike `raycast`: a pick sees through volumes. */
  triggers?: boolean
  /** What the pick passes through — the picker, whose own collider a ray from its eye starts inside. */
  exclude?: EntityHandle | string | (EntityHandle | string)[]
  /** A body heavier than this, kg, answers null. */
  maxMass?: number
  /** Only an entity with this tag answers; anything else in the way answers null. */
  tag?: string
}
```

Import: `import type { PickOptions } from "@argus/api"`

## Members

| Member | Signature | Description |
|---|---|---|
| `radius` | `radius?: number` | Sweep a sphere of this radius instead of a thin ray, metres — easier to aim at something small. Default 0. |
| `triggers` | `triggers?: boolean` | Whether a trigger volume stops the pick. Default **false**, unlike `raycast`: a pick sees through volumes. |
| `exclude` | `exclude?: EntityHandle \| string \| (EntityHandle \| string)[]` | What the pick passes through — the picker, whose own collider a ray from its eye starts inside. |
| `maxMass` | `maxMass?: number` | A body heavier than this, kg, answers null. |
| `tag` | `tag?: string` | Only an entity with this tag answers; anything else in the way answers null. |

## Example

The tested fixture `packages/critic/fixtures/play/door-and-key/key-pickup.ts`.

```ts
import type { Behavior, Ctx } from "@argus/api"

/**
 * The key: collected when the player reaches it.
 *
 * Two ways in, so the fixture works on every engine build: the trigger volume on this
 * entity fires `onTrigger` when the physics layer reports the player overlapping it, and a
 * proximity check each tick catches the case where a controller has no body to overlap
 * with. Either way the outcome is one `key-collected` event and the key leaving the level.
 */
interface State {
  collected: boolean
}

interface Props {
  /** Metres within which the player counts as touching the key. Default 1.2. */
  radius?: number
}

function collect(ctx: Ctx<State, Props>, by: string): void {
  if (ctx.state.collected) return
  ctx.state.collected = true
  ctx.events.emit("key-collected", { key: ctx.entity.id, tag: "key", by })
  ctx.log("key collected", { by })
  // Out of the level rather than despawned: nothing else needs to know it existed.
  ctx.entity.translate([0, -100, 0])
}

export default {
  init(ctx) {
    ctx.state.collected = false
  },
  update(ctx) {
    if (ctx.state.collected) return
    const radius = typeof ctx.props.radius === "number" ? ctx.props.radius : 1.2
    const near = ctx.world.query({ tag: "player", near: ctx.entity, radius })
    if (near.length > 0) collect(ctx, near[0]!.id)
  },
  onTrigger(ctx, trigger) {
    if (trigger.entering && trigger.other.hasTag("player")) collect(ctx, trigger.other.id)
  },
} satisfies Behavior<State, Props>
```
