Script Properties

Overview

Script properties let you configure behavior parameters from the Inspector without recompiling. Properties are stored as string key-value pairs on the NativeScript component and serialized with the scene.

Adding Properties in the Editor

  1. Select an entity with a NativeScript component
  2. Type a property name in the text field at the bottom of the component
  3. Click + Add
  4. Enter the value in the property field
  5. Press Enter to confirm

To remove a property, right-click on it.

Reading Properties in Code

Read properties in OnStart to initialize your behavior:

class MyBehavior : public Behavior {
public:
  void OnStart(flecs::entity e, Engine &engine) override {
    const auto *ns = e.get<NativeScript>();
    if (!ns)
      return;

    // Read a string property
    auto it = ns->properties.find("target");
    if (it != ns->properties.end()) {
      m_TargetName = it->second;
    }

    // Read a float property
    it = ns->properties.find("speed");
    if (it != ns->properties.end()) {
      m_Speed = std::atof(it->second.c_str());
    }
  }

private:
  std::string m_TargetName = "Player";
  float m_Speed = 5.0f;
};

Type Conversion

Properties are stored as strings. Convert them in OnStart:

// String (no conversion needed)
std::string name = ns->properties["target"];

// Float
float speed = std::atof(ns->properties["speed"].c_str());

// Integer
int count = std::atoi(ns->properties["count"].c_str());

// Boolean
bool enabled = (ns->properties["enabled"] == "true");

Include <cstdlib> for std::atof and std::atoi.

Serialization

Properties are saved to scene files automatically:

{
  "NativeScript": {
    "behaviorName": "MyBehavior",
    "properties": {
      "target": "Player",
      "speed": "5.0"
    }
  }
}

Helper Pattern

For behaviors with many properties, use a helper method:

class ConfigurableBehavior : public Behavior {
public:
  void OnStart(flecs::entity e, Engine &engine) override {
    const auto *ns = e.get<NativeScript>();
    if (!ns) return;
    ReadFloat(ns, "speed", m_Speed);
    ReadFloat(ns, "range", m_Range);
    ReadString(ns, "target", m_Target);
  }

private:
  void ReadFloat(const NativeScript *ns, const char *key, float &out) {
    auto it = ns->properties.find(key);
    if (it != ns->properties.end())
      out = std::atof(it->second.c_str());
  }

  void ReadString(const NativeScript *ns, const char *key, std::string &out) {
    auto it = ns->properties.find(key);
    if (it != ns->properties.end() && !it->second.empty())
      out = it->second;
  }

  float m_Speed = 5.0f;
  float m_Range = 10.0f;
  std::string m_Target = "Player";
};