LoginSignup
4
1

More than 3 years have passed since last update.

UdonSharp日記~道の動的生成3~

Last updated at Posted at 2020-04-30

モチベーション維持のためにLGTMください。

やったこと

今回は道の動的生成をバージョンアップさせました。
具体的には下記の2点を行いました。
1.障害物を設置することで迷路のような作りにすること
2.レシピを作成し、それを入力として生成するつくりにすること

1.の意図
 あらかじめプレハブで道のバリエーションを持っておくことも考えたのですが、逐次生成している都合、道の形状のつじつまが合わせられないケースがあると考え、障害物を設置することで迷路を作る構成としました。
 おいおい障害物を取り除くような処理を組むかもしれませんので、このやり方がよいかなと。
2.の意図
 現在、道のインスタンス化にVRCInstantiateを使用していますが、この関数は非同期です。同期を考えた場合、すべてのユーザーで同じようにVRCInstantiateを実行する必要があります。
 つまり、迷路のレシピを同期させておけば間接的に同期できるはずです。

やりかた

今回はUdonSharpの使い方というよりも、ゲームプログラミングとか設計とかそういう感じですね。

今回の大切なところは、迷路のレシピをどのように作成するかという点です。
道の形状はソースコード中0~6の数字が割り当たった7パターンと、その回転4パターンです。
どの形、どれくらいの回転、座標 この三つの情報がスタックされていれば、
途中から入ってきたプレイヤーも迷路を再現できるようになります。
(今回は同期についての実装はありません)

なおレシピのフォーマットは次の通りです。
nrx,y,z
n:道の形状
r:90度の回転回数
x,y,z(リスポーン地点を0,0,0とした際のマス目)

    //どのフロアを作成するか選定する
    //入力はフロアを作成する座標 と 北0, 東1, 南2, 西3どちらに進んでいるか0~3
    //出力はフロアのレシピ
    //フロアレシピ定義
    //フロア形状n(0~6) y軸回転r(0~3) 座標
    //n定義           r定義
    //0 :┼          0 : 0度
    //1 :│          1 : 90
    //2 :├          2 : 180
    //3 :┌          3 : 270
    //4 :・(行止り)
    //5 :↑上り階段
    //6 :↓下り階段
    private string FM_choiceGenerateFloor(Vector3 createPos, int orient)
    {
        int[] n_kouho;
        if ((int)createPos.y == 0)
        {
            //高さが0の時はフルセット
            n_kouho = new int[] { 0, 1, 2, 3, 4, 5, 6 };
        }else if ((int)createPos.y == (int)FM_FLOOR_HIGHT)
        {
            //高さが2階のとき
            n_kouho = new int[] { 0, 1, 2, 3, 4, 6 };//上りを除く
        }
        else
        {
            n_kouho = new int[] { 0, 1, 2, 3, 4, 5};//下りを除く
        }
        //候補からランダムに選択する
        int n = n_kouho[(int)Random.Range(0, n_kouho.Length)];

        int[] r_kouho;
        //道の形状によって許される回転回数が決まっている。(入り口には障害物を置いてはいけない)
        switch (n)
        {
            //01456は回転しない
            case 0:
            case 1:
            case 4:
            case 5:
            case 6:
                r_kouho = new int[] {0};
                break;
            case 2:
                //2は0,90,180の三択
                r_kouho = new int[] {0, 1, 2};
                break;
            case 3:
                //3は0,90の二択
                r_kouho = new int[] {0, 1};
                break;
            default:
                r_kouho = new int[] {0};
                break;
        }
        //回転もランダムに選択し、そこに、プレイヤーがどちらの方角から入ってきたかを加味する
        int r = (r_kouho[(int)Random.Range(0, r_kouho.Length)] + orient) %4;
        //座標そのままだとレシピが長いため、マス単位にする
        int x = (int)(createPos.x / (FM_FLOOR_SIZE_HALF * 2));
        int z = (int)(createPos.z / (FM_FLOOR_SIZE_HALF * 2));
        int y = (int)(createPos.y /  FM_FLOOR_HIGHT );
        return string.Format("{0}{1}{2},{3},{4}",n.ToString() , r.ToString() ,x,y,z);
    }

課題

まだこの方法で同期が実現できるかわかっていません。
近いうちに同期のテストを実施します。

同期テスト結果

同じワールドにいるならば同期できそうです。
後から入ってきた人もレシピをもとに同期をとるはずが、取れる場合と取れない場合がありました。

原因を探さねば

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1