HDS#19 グローバルな変数

こんにちは、開発担当の杉原です。

 

 

今週末は三連休。そろそろ暑さも落ち着いて、過ごしやすい時期になってきた(と思ってるのですが、引きこもりなのでよくわからないです)ので、どこかに出かけられる方も多いのではないでしょうか。

 

さて、久しぶりに通常路線に戻って行きたいと思います。

現在Demo3Dをご利用いただいているお客様から、Demo3Dの利用に関してお問い合わせをいただくことが多々あります。

私は基本的にはDemo3Dモデルなんかの開発を担当していますので、これらに直接対応する機会は少ないのですが、問い合わせメールは自分のもとにも届きますので、よく拝見させていただいています。

そんな中で、いくらかのお客様からはスクリプトに関するお問い合わせをいただくことがあります。

そのお問い合わせの中で、当ブログを見たうえでご質問をいただいているようでして、自分のブログを見てもらえているというのは嬉しい反面、まだまだブログでは伝えられていないことが沢山あるなぁと感じております。

 

というわけで、あるお客様から頂いたお問い合わせの中で、私が気になったものをピックアップしてご紹介していきたいと思います。

また、ちょっと難しい話にはなるかもしれませんが、その時の回答からさらに深堀もできればなぁと考えてます。

 

 

さて、今回ご紹介しますお問い合わせは

> 複数のVisualから参照されるScriptにおいて、グローバル変数はVisual毎に定義されるのでしょうか、それとも共有されるのでしょうか

> また、CustomPropertyとScriptのグローバル変数との扱いは異なるのでしょうか

といった内容のもの。

 

普段あまりグローバル変数は使わないので、自分も答えを知らなくて、ちょっと気になってました。

というわけで、以下のようなサンプルモデルを作成して、検証してみましょう。

モデル上には赤い箱を5つ、緑の箱を5つの計10個のVisualを配置してあります。

 

ここで2種類のVisualを用意している理由は、赤いBoxはJScriptでの実装、緑のSphereはC#での実装を行い、それぞれの動作について確認するためです。

 

実装したスクリプトはそれぞれ下記のようになります。

var GrobalCount = 0;

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
    if (!defined(sender.PropCount)) {
        sender.AddSimpleProperty("PropCount", 0, "");
    }
        
    sender.PropCount = sender.PropCount + 1;
    GrobalCount = GrobalCount + 1;
        
    print("[" + sender.Name + "][PropCount][" + sender.PropCount + "]");
    print("[" + sender.Name + "][GrobalCount][" + GrobalCount + "]");
}

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Demo3D.Native;
using Demo3D.Visuals;

[Auto] public class Sphere_CS : NativeObject {
    [Auto]
    SimplePropertyValue PropCount;
    
    int GrobalCount = 0;

    public Sphere_CS(Visual sender) : base(sender) {}
    
    [Auto] void OnReset(Visual sender) {
        PropCount.Value = PropCount.Value + 1;
        GrobalCount = GrobalCount + 1;
        
        print("[" + sender.Name + "][PropCount][" + PropCount.Value + "]");
        print("[" + sender.Name + "][GrobalCount][" + GrobalCount + "]");
    }
}

内容を簡単に説明します。

各Visualにはカスタムプロパティ「PropCount」を持たせます。

それと別に、カスタムプロパティではなくスクリプトのグローバルな変数として「GrobalCount」という値を定義しておきます(よく見たらスペルミスしてますね。。。。恥ずかしい)。

そしてOnResetイベントにて、各プロパティの値をインクリメントし、その結果をMessageLogに出力します。

この処理を5つのVisualから実行することによって、PropCountとGrobalCountがそれぞれどのようになるかを確認したいと思います。

 

では早速リセットしてみます。

まずはJScriptの結果から見てみましょう。

そのままのログだとC#と混在しているので、「Box」でフィルタリングをかけています。

結果、それぞれのPropCountはすべて1となっているのに対し、GrobalCountはどんどん加算されています。

このことから、CustomPropertyはVisualごとに独立しているのに対して、グローバル変数は各Visualで共有となっている、ということがわかります。

 

さてもう一方のC#はどうなったか見てみましょう。

なんということでしょう。こちらはPropCountもGrobalCountもすべて1となっているではありませんか。

どうやら、C#では値の共有がされないようですね。

 

 

以上の結果から、スクリプトとVisualの関係はJScriptとC#の場合で、それぞれつぎにようになっていると言えます。

JScriptの場合、上図のように1つの「JScriptオブジェクト」がモデル上に存在しており、それを複数のVisualが参照して利用しています。

一方で、C#の場合はVisualごとにスクリプトオブジェクトが生成されているということになります。

 

なぜこのような仕組みになっているのかは私の知るところではないのですが、

・JScriptは実行時にC#プログラムに書き換わって実行されること

・C#には[Auto]属性があること

といったところが理由かと考えられます。

 

じゃあ、もしもC#で実装するときに、各Visualで共通の値が使いたくなったときはどうすればいいのでしょうか。

それについては、次回ご説明したいと思います。


 

次回の【How to Demo3D Scripting】は「C#で共通変数を定義する」をお送りします。

更新は9/20(木)です。お楽しみに。