Help us understand the problem. What is going on with this article?

PlayCanvas Editorに外部スクリプトを読み込む新機能が追加されたので開発方法を考える。- Reduxを組み込む

More than 1 year has passed since last update.

はじめに

PlayCanvas EditorにExternal Scriptsという外部スクリプトを読み込むための機能が追加されました。

この機能ではエディターで設定をした外部のスクリプトを、起動時に

タグに挿入する機能となっております。機能自体はこの歯車の設定画面に追加されています。

外部スクリプトを追加する

今までのPlayCanvasではJavaScriptを埋め込む場合にはエディター上で埋め込むスクリプトを書かなければいけませんでしたがこのアップデートによりjQueryやFirebaseなどのSDKを埋め込む場合にもURLで指定が指定できるため、常に最新版を取ってくることができたりと便利になりました。

firebaseauth

追加したスクリプトはエディター上で起動をしたときにタグのPlayCanvasが読み込まれる前に挿入されます。

Head123

PlayCanvasのプロジェクトはこちらになります。

(公開リポジトリなのでフォークができます)
https://playcanvas.com/project/631609/

counter-vanillaを追加する

PlayCanvasはReactではないので、Reduxのサンプルの中のcounter-vanillaを使用してReduxの導入をします。

counter-vanilla/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic example</title>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div>
      <p>
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
        <button id="incrementIfOdd">Increment if odd</button>
        <button id="incrementAsync">Increment async</button>
      </p>
    </div>
    <script>
      function counter(state, action) {
        if (typeof state === 'undefined') {
          return 0
        }
        switch (action.type) {
          case 'INCREMENT':
            return state + 1
          case 'DECREMENT':
            return state - 1
          default:
            return state
        }
      }
      var store = Redux.createStore(counter)
      var valueEl = document.getElementById('value')
      function render() {
        valueEl.innerHTML = store.getState().toString()
      }
      render()
      store.subscribe(render)
      document.getElementById('increment')
        .addEventListener('click', function () {
          store.dispatch({ type: 'INCREMENT' })
        })
      document.getElementById('decrement')
        .addEventListener('click', function () {
          store.dispatch({ type: 'DECREMENT' })
        })
      document.getElementById('incrementIfOdd')
        .addEventListener('click', function () {
          if (store.getState() % 2 !== 0) {
            store.dispatch({ type: 'INCREMENT' })
          }
        })
      document.getElementById('incrementAsync')
        .addEventListener('click', function () {
          setTimeout(function () {
            store.dispatch({ type: 'INCREMENT' })
          }, 1000)
        })
    </script>
  </body>
</html>

counter-vanilla/index.htmlはindex.htmlだけあれば特にフレームワークを必要としないサンプルとなっています。
それではこのScriptをPlayCanvasに組み込んでいきましょう

  1. External ScriptsへReduxの最新版を追加 index.html内のScript srcで読み込まれているスクリプトをExternal Scriptsの中へ追加します。

https://unpkg.com/redux@latest/dist/redux.min.js

2.HTML, CSSをPlayCanvas Editorに追加します。

index.html
      <p id="counter">
        Clicked: <span id="value">0</span> times
        <button id="increment">+</button>
        <button id="decrement">-</button>
      </p>
style.css
#counter{
    position: absolute;
    z-index: 1;
    color: red;
}

button{
    padding: 10px;
}
  1. Store, HTML,CSSの表示をする部分のScriptを追加しAttributesに追加をする HTMLをPlayCanvas上に追加をする為にAttributesとしてEditor上で先ほどEnditor上に追加をしたHTMLとCSSセットします。

Ui.js
constUi = pc.createScript("ui");

Ui.attributes.add("css", {
  type: "asset",
  assetType: "css",
  title: "CSS Asset"
});
Ui.attributes.add("html", {
  type: "asset",
  assetType: "html",
  title: "HTML Asset"
});

const counter = (state, action) => {
    if (typeof state === 'undefined') {
      return 1
    }
    switch (action.type) {
      case 'INCREMENT':
        return state + 1
      case 'DECREMENT':
        return state - 1
      default:
        return state
    }
}

const store = Redux.createStore(counter)

Ui.prototype.initialize = function() {
  const body = document.getElementsByTagName("body")[0];
  const head = document.getElementsByTagName("head")[0];
  const style = `<style>${this.css.resource}</style>`;
  body.insertAdjacentHTML("afterbegin", this.html.resource);
  head.insertAdjacentHTML("afterbegin", style);
  //HTML, CSSを挿入する

  var valueEl = document.getElementById('value')
  function render() {
    valueEl.innerHTML = store.getState().toString()
  }
  render()
  store.subscribe(render)
  document.getElementById('increment')
    .addEventListener('click', function () {
      store.dispatch({ type: 'INCREMENT' })
    })
  document.getElementById('decrement')
    .addEventListener('click', function () {
      store.dispatch({ type: 'DECREMENT' })
    })

};

このScriptを追加することでPlayCanvas上にカウンターが追加されました。

コンポーネントにStateの値を適用させる

テキストコンポーネント

このままだと、HTMLを上にかぶせているだけです、Reduxの状態を参照してインクリメントした文字に変更するエンティティを追加します。  
1. 2D Screenを追加  

  1. 2D Screen以下にTextエンティティを追加
  2. フォントを追加  

4.Scriptを追加する

Textエンティティに対してtext.jsというスクリプトを追加します。

text.js
const Text = pc.createScript('text');
Text.prototype.update = function(dt) {
    this.entity.element.text = store.getState().toString()
};

カメラの値を変更する

  1. Cameraエンティティにcamera.jsを追加する
camera.js
const Camera = pc.createScript('camera');

Camera.prototype.update = function() {
     this.entity.camera.fov = store.getState() * 2 - 30
};

これでReduxのアクションによりCameraエンティティのfovが寄る、Textエンティティの値を変更することができました
output

PlayCanvasのプロジェクトはこちらになります。

疑問

Update関数で毎秒評価しているのはどうなんだろう

Reduxの3原則は守れてそう
- Single source of truth
- State in read-only
- Changes are made with pure functions

yushimatenjin
インターネットに無限の可能性を感じています。
https://twitter.com/Mxcn3
playcanvas
"PlayCanvasは、ブラウザ向けに作られたWebGL/HTML5ゲームエンジンです。PlayCanvas運営事務局は日本国内でのPlayCanvasの普及を目的に活動しています"
https://playcanvas.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした