【Unity】インターフェースのデフォルト実装はビルド後の動作が違う話

対象読者

  • UnityのWebGLでのビルド後の動作が変わって困っている人

記事の内容

  • 特定の条件下でインターフェースのデフォルト実装を使用したとき、WebGLビルド後の動作が変わる原因の解説をする

実際に問題が発生するコード


public interface IHogeValue
{
   int Value { get; set; }

   int GetValue()
   {
      return Value;
   }
}

public class HogeParent : IHogeValue
{
   public int Value { get; set; }

   public HogeParent()
   {
      Value = 1;
   }
}

public class HogeChild : HogeParent, IHogeValue
{
   new public int Value { get; set; }

   public HogeChild()
   {
      Value = 2;
   }

}

public class Logger : MonoBehaviour
{
   void Start()
   {
      IHogeValue child = new HogeChild();
      Debug.Log(child.GetValue());
      Debug.Log(((IHogeValue)child).GetValue());
      Debug.Log(child.Value);
      Debug.Log(((IHogeValue)child).Value);
      Debug.Log(((HogeParent)child).Value);
   }
}

実際に動作させると、Loggerの出力結果は、Windowsビルドの場合は「1 1 2 1 1」、WebGLビルドの場合は「2 1 2 1 1」となります。

2つのビルドにおいて、変数「child」が保持している変数の値は同じで、プロパティから呼び出しても動作は同じだけど、関数からプロパティを呼びだしときだけ、動作が変わります。

予防法

  • 曖昧なプロパティを作らない

今回の場合だと、「HogeChildのValue」が曖昧なプロパティです。

このプロパティを消すと、WindowsとWebGLで動作は同じになります。

問題が発生する条件

  • 子クラスと親クラスに付けられたinterfaceは異なるが、同名の関数を持っている
  • 継承しているinterfaceにデフォルト実装がされている
  • 同名関数内で同名プロパティを使った処理をする
  • 子クラスから、その関数を呼び出す

まとめ

  • WebGLビルドをするなら、インターフェースのデフォルト実装の使い方に注意
  • 普通の書き方をすれば、殆ど問題は発生しない
  • 特殊な書き方をしても、「曖昧な関数やプロパティ」を消す事で問題が解消できる場合がある

【javascript】サイト上で音を鳴らす方法【2024年】

導入

2018年、Googleのポリシーが変更になり、javascriptでただAudioオブジェクトを作って、play()を呼ぶだけでは、音を鳴らすことができなくなりました。

様々なサイトで、すでに無効になった上記の方法が紹介されていて、2018年以降の方法を紹介しているサイトがあまりなかったので、ここに方法を書いておきます。

方法

①ユーザーにサイトをクリックをさせる。

②AudioContextオブジェクトのresume()を呼ぶ。

③その後に音を鳴らす。

(①と②は逆でも良いです。)

コード例

const atx = new AudioContext();
atx.resume();
const snd = new Audio("オーディオファイルへのパス.mp3");
document.addEventListener("click",() => {
     snd.currentTime = 0;
     snd.play();
})

上のコードは、クリックすると音が鳴るコードです。

currentTime = 0は、再生場所を設定しています。再生場所を元に戻さないと、連続再生しても、前の音が終わるまで次の音が鳴りません。

また、AudioContextのstateというプロパティで「音声が許可されたかどうか」が確認できます。stateが「running」の場合は許可あり、「suspended」の場合は許可なし、です。

ブラウザゲームを作る場合は、ミュートをデフォルトの設定するか、クリックするとゲームが始まるように設計すると良さそうです。

参考文献

https://developer.chrome.com/blog/autoplay

【ゲーム制作】敵AIを数学的理論を基に作成する① ~UCB1方策~

導入

スマブラなどの格闘ゲームからオセロなどの戦略ゲームに至るまで、敵のAIが必要になります。今回は、数学的に性能が保証された戦略AIを作成する方法を紹介します。

今回は、「UCB1方策」というものを紹介します。

UCB1方策の概要

UCB1方策というのは、多腕バンディット問題に対する戦略の一つです。

多腕バンディット問題とは、複数の「報酬の期待値が分かっていない」選択肢があるときに、報酬を最大化する選択肢の選び方を考える問題です。

多腕バンディット問題の例は、「勝率が不明な複数のスロットがあって、金貨をどういう風に入れたら報酬を最大化できるか」という問題です。

UCB1方策の具体的な手順

①まず、全ての選択肢を1回ずつ試します。

②その後、UCBスコアが最大になる選択肢を試します。(UCBスコア=μ+c√(ln(N)/n))

(μ:その選択肢の現時点の勝率。c:定数。理論上は√2だが問題によって調整する必要がある。小さくするほど現時点の勝率を重要視し、大きくするほど探索を重要視する。N:全ての選択師の探索回数の合計、n:その選択肢の探索回数。)

(※lnは自然対数で、logの底がネイピア数eであるものです。)

③手順②を繰り返します。

UCB1方策が戦略ゲームのAIに使える理由

戦略ゲームはモンテカルロ法を使うことにより「多腕バンディット問題」とみなすことができるからです。

モンテカルロ法とは、乱数を使って特定の値を推定する方法です。ランダムに点を打って、円の面積を推定するのもモンテカルロ法です。

ある選択肢を選んだとき、「それ以降の選択肢はどちらかが勝つまで完全にランダムに選び、勝敗を決める」とします。

1つの選択を選ぶと、ある特定の確率で「勝利」という報酬を得られるので、これは多腕バンディット問題になっています。

「選択肢を試す=1$失う」、「勝利=10$貰う」などと考えると分かりやすいです。

UCB1方策の実現例

RPGゲームの戦闘で、ドラゴンAIに最適な行動を選ばせる場合を考えます。

選択肢は、「A:殴る」「B:火を吐く」「C:力を溜める」です。

まずは手順①。Aを選ぶと結果は「敗北」。B、Cは「勝利」でした。

現在のUCBスコアは、Aは0、B、Cは1。

続いて手順②。定数c=√2とします。Bを選ぶと結果は「敗北」でした。

現在のUCBスコアは、Aは√(2ln2)≒1.18、Bは1/2+√(ln2)≒1.33、Cは1+√(2ln2)≒2.18

再度②。Cを選ぶと結果は「勝利」でした。

現在のUCBスコアは、Aは√(2ln3)≒1.48、Bは1/2+√(ln3)≒1.55、Cは1+√(ln3)≒2.05.

再度②。Cを選ぶと結果は「敗北」でした。

現在のUCBスコアは、Aは√(2ln4)≒1.67、Bは1/2+√(ln4)≒1.68、Cは2/3+√(2ln4/3)≒1.63

再度②。Bを選ぶと結果は「敗北」でした。

(本来は何十回、何百回とする必要がありますが、今回はここで終了します。)

現在、最も勝率が高い選択肢はCなので、ドラゴンはCを選択する。

問題点

UCB1方策は、原始モンテカルロ法を少し改良した程度の戦略です。なので、まだまだ全然弱いです。

※今回は、このUCB1方策に探索木を組み合わせたUCTという強力な方策を紹介する準備として紹介しました。

数学的理解

UCB1方策の手順②の式を導出したい人向け。

↓ 研究者の方が書かれている記事です

多腕バンディット問題におけるUCB方策を理解する · THINKING MEGANE (monochromegane.com)

↓ 多腕バンディットに使われる統計学の定理の紹介

参考文献

https://www.kurims.kyoto-u.ac.jp/~kyodo/kokyuroku/contents/pdf/1894-14.pdf

https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%AB%E3%83%AB%E3%83%AD%E6%9C%A8%E6%8E%A2%E7%B4%A2

https://ja.wikipedia.org/wiki/%E5%A4%9A%E8%85%95%E3%83%90%E3%83%B3%E3%83%87%E3%82%A3%E3%83%83%E3%83%88%E5%95%8F%E9%A1%8C