Reference

Scripting API

This page summarizes the main gameplay scripting surface.

Base Types

Sendama\Engine\Core\Component

The base class for engine components.

Useful members and hooks:

  • getGameObject()
  • getTransform()
  • getRenderer()
  • awake()
  • onStart()
  • onUpdate()
  • onFixedUpdate()
  • onStop()
  • onResume()
  • onSuspend()
  • enable()
  • disable()
  • isEnabled()

Minimal component example:

<?php

namespace Sendama\MyGame\Scripts;

use Sendama\Engine\Core\Component;

class ScorePulse extends Component
{
  public function onStart(): void
  {
    $this->getGameObject()->setTag('ui-score');
  }

  public function onUpdate(): void
  {
    $position = $this->getTransform()->getPosition();
    $position->setX($position->getX() + 1);
    $this->getTransform()->setPosition($position);
  }
}

Sendama\Engine\Core\Behaviours\Behaviour

The standard base class for custom gameplay logic.

Adds convenience accessors:

  • activeScene
  • scene

Collision and trigger hooks:

  • onCollisionEnter(CollisionInterface $collision)
  • onCollisionStay(CollisionInterface $collision)
  • onCollisionExit(CollisionInterface $collision)
  • onTriggerEnter(ColliderInterface $collider)
  • onTriggerStay(ColliderInterface $collider)
  • onTriggerExit(ColliderInterface $collider)

Typical behaviour example:

<?php

namespace Sendama\MyGame\Scripts;

use Sendama\Engine\Core\Attributes\SerializeField;
use Sendama\Engine\Core\Behaviours\Behaviour;
use Sendama\Engine\Core\Vector2;
use Sendama\Engine\IO\Input;
use Sendama\Engine\IO\Enums\AxisName;

class PlayerController extends Behaviour
{
  #[SerializeField]
  private int $speed = 1;

  #[SerializeField]
  private ?Vector2 $spawnPoint = null;

  public function onStart(): void
  {
    if ($this->spawnPoint) {
      $this->getTransform()->setPosition($this->spawnPoint);
    }
  }

  public function onUpdate(): void
  {
    $movement = new Vector2(
      x: (int) round(Input::getAxis(AxisName::Horizontal) * $this->speed),
      y: (int) round(Input::getAxis(AxisName::Vertical) * $this->speed),
    );

    $this->getTransform()->translate($movement);
  }
}

Serialization Rules

Scene and prefab metadata can assign values to component properties when the scene is loaded.

Supported targets:

  • public properties
  • protected or private properties marked with #[SerializeField]

Supported metadata payload keys:

  • data
  • properties
  • proerties

The editor currently emits data.

SerializeField

Use #[SerializeField] on non-public fields that should be editable or serializable through scene/prefab metadata.

Typical use cases:

  • float tuning values
  • bool toggles
  • Vector2 bounds
  • prefab references
  • pool sizes

Example with a pooled projectile setup:

<?php

namespace Sendama\MyGame\Scripts\Weapons;

use Sendama\Engine\Core\Attributes\SerializeField;
use Sendama\Engine\Core\Behaviours\Behaviour;
use Sendama\Engine\Core\GameObject;
use Sendama\Engine\Core\Interfaces\GameObjectInterface;

class Gun extends Behaviour
{
  #[SerializeField]
  private ?GameObjectInterface $bulletPrefab = null;

  #[SerializeField]
  private int $poolSize = 24;

  /** @var GameObjectInterface[] */
  private array $bulletPool = [];

  public function onStart(): void
  {
    if ($this->bulletPrefab) {
      $this->bulletPool = GameObject::pool($this->bulletPrefab, $this->poolSize);
    }
  }
}

Input Facade

Sendama\Engine\IO\Input exposes static helpers for input checks.

Method Purpose
Input::getAxis(AxisName $axisName): float Read a virtual axis
Input::isKeyPressed(KeyCode|string $keyCode): bool Check held key
Input::areAllKeysPressed(array $keyCodes): bool Require all keys
Input::isAnyKeyPressed(array $keyCodes, bool $ignoreCase = true): bool Require any key
Input::isAnyKeyReleased(array $keyCodes): bool Detect release in a set
Input::isKeyDown(KeyCode|string $keyCode): bool Detect key-down edge
Input::isKeyUp(KeyCode|string $keyCode): bool Detect key-up edge
Input::isButtonDown(string $buttonName): bool Read named button

Example fire input check:

<?php

use Sendama\Engine\IO\Input;

if (Input::isButtonDown('fire') || Input::isKeyDown('space')) {
  $this->fireWeapon();
}

Authoring Pattern

The most maintainable script pattern in Sendama is:

  1. keep scene and prefab files declarative
  2. keep behavior in Behaviour classes
  3. expose only the fields designers should tune
  4. use prefabs and serialized references instead of hard-coding every object in PHP

Collision handling is usually most maintainable when the receiving object reacts to the other collider directly:

<?php

use Sendama\Engine\Physics\Interfaces\ColliderInterface;

public function onTriggerEnter(ColliderInterface $collider): void
{
  $other = $collider->getGameObject();

  if (!$other) {
    return;
  }

  if ($other->getTag() === 'enemy') {
    $other->deactivate();
    $this->getGameObject()->deactivate();
  }
}