AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

バーチャルパッドを試した

以下の記事で紹介されていたバーチャルパッドを試してみました。
kan-kikuchi.hatenablog.com

バーチャルジョイパッドのアナログジョイスティック

f:id:yasu9780:20170201142849g:plain

おかげさまであっさり実装できました。


右と左のアナログジョイスティックが欲しいので、

[SerializeField]
private Joystick _joystickR = null;

[SerializeField]
private Joystick _joystickL = null;

と二つ宣言して、値は

float ax = _joystickL.Position.x;
float ay = _joystickL.Position.y;

float ax2 = _joystickR.Position.x;
float ay2 = _joystickR.Position.y;

で取れました。

f:id:yasu9780:20170201144124p:plain
このバーチャルパッドはuGUI部品として実装されています。


元ソース(Joystick.cs)のスティックが指定範囲を超えた場合に円内に戻す処理ですが、

    if(currentRadius > _radius){

      //角度計算
      float radian = Mathf.Atan2(_stick.transform.localPosition.y, _stick.transform.localPosition.x);

      //円上にXとYを設定
      Vector3 limitedPosition = Vector3.zero;
      limitedPosition.x = _radius * Mathf.Cos (radian);
      limitedPosition.y = _radius * Mathf.Sin (radian);

      _stickPosition = limitedPosition;
    }


三角関数を使ってやってますが、ベクトル長の補正だけでいけます。
これで大丈夫。三角関数は遅いのでなるべく使わない方がベターと思います。

    if (currentRadius > _radius)
    {
        _stickPosition = _stick.transform.localPosition.normalized* _radius;
    }

ジョイパッドのボタン

indie-du.com
上記記事を参考に、ボタン画像にEventTriggerコンポーネントを追加して、
記事のソースのImage ClickImageに該当ボタン画像をドラッグして登録したら、
クリックでClickedが呼ばれました。


あんまりスマートじゃない感じだけど、
imageがクリックされたら呼ばれるコールバックでブール変数をtrueにして、
ゲームの処理本体からフラグを見て、動かすみたいな感じで動いた。
連打しても大丈夫っぽい。

bool KeyPadA = false;
void ClickedA(BaseEventData eventData)
{
    keypadA = true;
    Debug.Log("ClickedA");
}

bool isCrouch=false;
void Update
{
    // Virtual or Real A button
    if(keypadA || Input.GetKeyDown("joystick button 0"))
    {
        isCrouch = !isCrouch;
        anim.SetBool("Crouch", isCrouch);
        keypadA = false;
    }
}

flagを見る側落とさないといけないのはなんか嫌なので、
ジョイパッド側で、FixedUpdateでflagを落とせばいけた。

イベント実行順序的にFixedUpdateは最初なので、
まず落としておいて、
Inputイベント系のClickedコールバックがフラグを立てて、
次にゲーム本体のUpdateがフラグを見れば、
キャラが半立ちになり、
つぎのUpdateの時にはフラグは落ちているので、上下運動はしない。

Unity - マニュアル: イベント関数の実行順

void FixedUpdate()
{
   if (onClicked) onClicked = false;
}
void Clicked(BaseEventData eventData)
{
    onClicked = true;
    Debug.Log("Clicked");
}

タッチ始点のジョイパッドに改造

ビルドして実際にスマホで操作してみると、タッチ始点のジョイパッドじゃないとまともに操作できないことが判明。

検索すると、同じ作者様がタッチ始点バージョンも作っていたので試してみる。
kan-kikuchi.hatenablog.com

これはシングルトンのTouchEventHandlerがタッチ関連のイベントをjoystickに渡すように作られていて、このTouchEventHandlerのUIの範囲が、タッチ始点として有効という作りになっている。

しかし、右と左で二つジョイパッドを登録すると、どちらも同時に動いてしまう。
どちらも同じTouchEventHandlerからイベントをもらっているので当然の動き。

そこでTouchEventHandlerを二つにしたい。左右で。
ただしシングルトンなので、二つ作れないので、まずシングルトンをやめる。
TouchEventHandlerはImageなので、領域が重ならいように左右にわけて二つ作る。
ここでは、
TouchEventHandlerL,TouchEventHandlerRとした。

以上で、左右別々のタッチ始点範囲を持って別々に動くジョイスティックが作れた。
この仕様なら、タッチ始点範囲を分ければ、いくつでもアナログジョイパッドを同時に作れる。


改造範囲は、

public class TouchEventHandler : SingletonMonoBehaviour<TouchEventHandler>,
 ↓シングルトンやめる
public class TouchEventHandler : MonoBehaviour,

joystick.csに親のハンドラーを追加

        [SerializeField]
        private TouchEventHandler touchEventHandler;

イベント登録をシングルトンではなく、インスペクターで登録したハンドラーに対して行う

            //操作関連のイベントを登録
            touchEventHandler.onBeginPress += OnBeginPress;
            touchEventHandler.onEndPress += OnEndPress;
            touchEventHandler.onEndDrag += OnEndDrag;
            touchEventHandler.onDrag += OnDrag;

バーチャルジョイパッドとリアルジョイパッド両対応できた!

f:id:yasu9780:20170201181925p:plain