Build a Shared Score Panel in Banter

Banter public space properties hold shared values for a space. Combine SetPublicSpaceProps() with space-state-changed and the Banter UI system to show a score that responds to state updates.

Shared Score Workflow

Create a world-space UI panel, add a label and button, then connect the controls to a public space property.

  1. Create a BanterUIPanel and add a score label.
  2. Write score changes with SetPublicSpaceProps().
  3. Update the label from space-state-changed.

Create the World-Space Panel

BanterUIPanel must first be added to a GameObject. Set screenSpace to false for a panel placed in the scene:

const panelObject = new BS.GameObject({
  name: "SharedScorePanel",
  localPosition: new BS.Vector3(0, 2, 3)
});

const panel = panelObject.AddComponent(
  new BS.BanterUIPanel({
    resolution: new BS.Vector2(800, 600),
    screenSpace: false,
    enableHaptics: true,
    clickHaptic: new BS.Vector2(0.1, 0.05),
    enterHaptic: new BS.Vector2(0.05, 0.02),
    exitHaptic: new BS.Vector2(0.05, 0.02),
    enableSounds: false
  })
);

The haptic vectors contain amplitude and duration values in the official component example.

Add the Score Label

Create a UILabel, set its text and style, then append it to the panel root:

const scoreLabel = new BS.UILabel();
scoreLabel.SetProperty(BS.PN.text, "Score: 0");
scoreLabel.style.fontSize = "36px";
scoreLabel.style.color = "#FFFFFF";
panel.root.AppendChild(scoreLabel);

Keep the scoreLabel reference so the state event can change its text.

Add an Increment Button

let score = 0;

const addButton = new BS.UIButton();
addButton.SetProperty(BS.PN.text, "Add Point");
addButton.style.width = "200px";
addButton.style.height = "50px";
addButton.style.backgroundColor = "#4CAF50";
addButton.style.color = "#FFFFFF";

addButton.OnClick(() => {
  scene.SetPublicSpaceProps({
    gameScore: String(score + 1)
  });
});

panel.root.AppendChild(addButton);

The official state example stores values such as gameScore as strings.

Listen for Shared Score Changes

space-state-changed supplies a changes collection. Each change includes the property name, old value, and new value:

scene.On("space-state-changed", (event) => {
  for (const change of event.detail.changes) {
    if (change.property !== "gameScore") {
      continue;
    }

    score = Number(change.newValue) || 0;
    scoreLabel.SetProperty(
      BS.PN.text,
      `Score: ${score}`
    );
  }
});

Filter by property name before updating the display because the event may report changes to other public space properties.

Send an Event Instead of Storing State

For an action that does not need to remain as the current score, Banter also provides one-shot messages:

scene.OneShot({
  type: "score-effect",
  data: { value: score }
}, true);

Use a public space property for the current score and a one-shot message for a discrete action that listeners handle as an event.

Common Questions

Why does my Banter score label never change?

Confirm that the listener checks the same property name passed to SetPublicSpaceProps(). In this example, both use gameScore.

Should the score use a public property or a one-shot message?

Use the public property for the value that represents the current score. Use a one-shot message for a separate event that does not need to remain as stored state.

Official References

Related Navigation