【PlayCanvas(JavaScript)】PlayCanvasを触ってみた


PlayCanvas

PlayCanvasは、デスクトップとモバイルブラウザ向けに作られた
WebGL/HTML5ゲームエンジンです。豊富な機能を揃えた3Dエンジンと
クラウドホスティングされた開発環境およびツールセットを備えています。

引用元:PLAYCANVAS

サンプルも非常に多くチュートリアルも丁寧でありがたいです。
Unityに似たところもあるのでUnityエンジニアの方はとっつきやすいと思います。
※ただしJavaScript

私自身Unityをメインウエポンとしてお仕事やらせていただいているので
ところどころUnityと比較しながらメモしていきます。

今回はPlayCanvasに慣れるためにチュートリアルの簡単そうなことを中心に試してみます。

JavaScriptを書いたことないので酷いこと書いてるかもしれません。
どうか優しくしてやってください。

下準備

アカウントを作成してログインしたらHomeからプロジェクトを作成します。

Entity

まず最初に理解しないといけないのはEntityかな~と思いました。

PlayCanvasはゲーム内の全てのオブジェクトがEntityと呼ばれます。
Unityで言うところのGameObjectみたいな感じです。

Editor上のHIERARCHYから新しいEntityを生成すると下記画像のように
何の振るまいも持たない空のEntityが生成されます。

ADD COMPONETを選択していろいろな振るまい(Component)を追加することができます。

【参考リンク】:エンティティ

Script作成

先ほどのADD COMPONETで追加する振る舞いですが、
自分で独自のものを定義することができます。

それがScriptと呼ばれるものです。

Editor上のASSETS配下にJavaScriptのファイルを作成してその中に記述していきます。

試しにtestというScriptを作成してみます。
(Lower camel caseで作成するのが慣習?)

何も追記してないデフォルトの状態
var Test = pc.createScript('test');

// initialize code called once per entity
Test.prototype.initialize = function() {

};

// update code called every frame
Test.prototype.update = function(dt) {

};

// swap method called for script hot-reloading
// inherit your script state here
// Test.prototype.swap = function(old) { };

// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/

initialize

initializeはUnityで言うところのAwakeStartとほとんど同じように振るまいます。

簡潔に述べると初期化時に各Entityごとに呼び出されます。
初期化時とはいつか?というのは下記のような記述が公式チュートリアルに記述がありました。

最初の更新ループまたはフレームのレンダリングされる前に呼び出されます

【参考リンク】:スクリプトの構造

Entity及びScriptがenableになったタイミングでinitializeが呼ばれる辺りも
Unityと似ています。

【参考リンク】:【PlayCanvas】Tips


update

updateはUnityで言うところのupdateとほとんど同じように振るまいます。

引数のdtはDeltaTimeのことで、1フレーム分を更新するために経過した時間を指します。

postUpdateと呼ばれるUnityで言うところのLateUpdate?のような
振るまいをしてくれそうなメソッドもありました。

postUpdateは、すべてのスクリプトが更新された後に呼び出されるupdateメソッドです。すべてのスクリプトが更新されていると仮定することができる機能を実行するために使用します。例えば、他のエンティティを追跡するカメラは、別のエンティティがフレームで動作を完了できるように、postUpdateでその位置を更新する必要があります。

【参考リンク】:スクリプトの構造

Attribute

AttributeはUnityで言うところの
[SerializeField]publicで宣言したフィールド変数のような振るまいをしてくれます。

簡潔に述べると、アトリビュートはEntity同士で参照を持たせる際に便利な機能です。

下記にサンプルを用意しました。
logという文字通りログを出すだけのScriptを作成し、
testから参照してメソッドを呼び出してみます。

log:適当なEntityにアタッチ
var Log = pc.createScript('log');

//testで呼び出してもらう
Log.prototype.successRef = function(){
    console.log('他のScriptからの参照に成功');
};

test:適当なEntityにアタッチ
var Test = pc.createScript('test');

Test.attributes.add('logEntity', {type: 'entity', title: 'Log Entity'});

Test.prototype.initialize = function() {
    //アトリビュートで参照したEntityからScriptコンポーネントを取得
    var logScript  = this.logEntity.findComponent('script');
    //取得したScriptコンポーネントからLogを出すメソッドを呼び出す
    logScript.log.successRef();
};

Test.attributes.addの箇所がアトリビュートです。
今回のコードで言うとlogEntityがコード内で参照可能な変数名です。
typeの後は型名のようなものです。
stringbooleanもこのtypeで指定できると言えばわかりやすいかもしれません。

あとはUnityでInspectorにアタッチする要領で
Editor上でドラッグアンドドロップすればOKです。
ただし、下記のパースボタンを一度押下しないとアトリビュートが表示されないので要注意です。

実行してブラウザ上でF12キーを押してコンソールを開いてみます。
無事、他のScriptのメソッド呼び出しができました。


Scriptが複数の場合

Scriptが複数の場合を見ていきます。
例としてlog2というScriptをlogを既に設定してあるEntityに設定してみます。

log2:logがアタッチされたEntityにアタッチ
var Log2 = pc.createScript('log2');

//testで呼び出してもらう
Log2.prototype.successRef = function(){
    console.log('Log2:他のScriptからの参照に成功');
};
test:適当なEntityにアタッチ
var Test = pc.createScript('test');

Test.attributes.add('logEntity', {type: 'entity', title: 'Log Entity'});

Test.prototype.initialize = function() {
    var logScript  = this.logEntity.findComponent('script');
    logScript.log.successRef();
    logScript.log2.successRef();
};

Scriptの中に追加したloglog2のメソッドをそれぞれ呼び出せました。

findComponent('script')でそのEntityにアタッチされたScriptを取得すれば、
全部まとめて利用することができるのは便利だなと思いました。

おわりに

まだまだPlayCanvasの1パーセント程度も触り切れていませんが
入門の入門レベルでは理解できました。

VR、ARもできる?っぽいのでその辺りも触っていきたいです。