岡オカ営業所 ホームへ

BveHacker.Scenarioプロパティに注意!「シナリオの読込が完了していないため、Scenario プロパティの値は取得できません。」と表示されたら

公開 2025/04/15
更新 2025/04/16

表題のようなエラーが表示される場合、BVE本体がシナリオを読み込み終わる前に、BveEXプラグインからシナリオへアクセスしようとしてしまっています。

次のようなコードがありませんか?

Scenario scenario = BveHacker.Scenario;
// -- あるいは --
BveHacker.Scenario.~略

BveHacker.Scenario プロパティは、BVE本体がシナリオを完全に読み込んで以降でないと、取得することはできません

具体的には、例えばBveEXプラグインのコンストラクタはシナリオの読込完了前になります。よって次のコードを実行すると表題のエラーが発生します。

public class PluginMain : AssemblyPluginBase
{
    private AssistantText TestText;

    public PluginMain(PluginBuilder builder) : builder
    {
        // 始発駅の距離程を取得して、補助表示に出力したい
        // しかし、シナリオの読込完了前に BveHacker.Scenario プロパティへアクセスしているのでエラーとなる
        double firstStationLocation = BveHacker.Scenario.Map.Stations[0].Location;
        
        // 補助表示を作成・追加
        TestText = AssistantText.Create($"始発駅の距離程は {firstStationLocation} m です。");
        BveHacker.Assistants.Items.Add(TestText);
    }

    public void Dispose()
    {
        // 補助表示を削除・解放
        BveHacker.Assistants.Items.Remove(TestText);
        TestText.Dispose();
    }

    // ...略
}

プラグインを読み込んだ直後にシナリオを取得するには

BveHacker.ScenarioCreated イベント を購読してください。

このイベントは BveHacker.Scenario プロパティが取得可能となる直前に発生し、その中でシナリオへアクセスすることができます。

プラグインの Tick メソッドの冒頭で読込直後かどうかを判定しても良いのですが、こちらを使用した方がよりスマートに実装できるのでおすすめです。

上記のエラーとなるコードと同等のものを BveHacker.ScenarioCreated イベントで実装すると、次のようになります。

// using BveEx.PluginHost; を追加

public class PluginMain : AssemblyPluginBase
{
    private AssistantText TestText;

    public PluginMain(PluginBuilder builder) : builder
    {
        // イベントの購読
        BveHacker.ScenarioCreated += OnScenarioCreated;
    }

    public void Dispose()
    {
        // イベントの購読解除を忘れずに
        BveHacker.ScenarioCreated -= OnScenarioCreated;
        
        BveHacker.Assistants.Items.Remove(TestText);
        TestText.Dispose();
    }

    private void OnScenarioCreated(ScenarioCreatedEventArgs e)
    {
        // このイベント内でシナリオへアクセスする場合も、BveHacker.Scenario プロパティはやはり使用不可なので注意
        // シナリオは ScenarioCreatedEventArgs の Scenario プロパティから取得できる
        double firstStationLocation = e.Scenario.Map.Stations[0].Location;
        
        TestText = AssistantText.Create($"始発駅の距離程は {firstStationLocation} m です。");
        BveHacker.Assistants.Items.Add(TestText);
    }

    // ...略
}

BveHacker.Scenario プロパティが使用可能かどうかを知るには

BveHacker.IsScenarioCreated プロパティ から取得可能です。

public class PluginMain : AssemblyPluginBase
{
    public PluginMain(PluginBuilder builder) : builder
    {
        BveHacker.ScenarioCreated += OnScenarioCreated;

        // false になる
        bool isScenarioCreated = BveHacker.IsScenarioCreated;
    }

    public void Dispose()
    {
        BveHacker.ScenarioCreated -= OnScenarioCreated;
        
        // false になる
        // ここでも BveHacker.Scenario プロパティを使用できないことには変わりないため
        bool isScenarioCreated = BveHacker.IsScenarioCreated;
    }

    private void OnScenarioCreated(ScenarioCreatedEventArgs e)
    {
        // true になる
        bool isScenarioCreated = BveHacker.IsScenarioCreated; // true になる
    }

    // ...略
}

こちらも参考にどうぞ

ブログ トップへ戻る