LoginSignup
3
2

More than 3 years have passed since last update.

UdonSharp日記~道の動的生成~

Last updated at Posted at 2020-04-27

やったこと

前回プレイヤーの座標を取得しました。
UdonSharp日記~ローカルプレイヤーの座標の取得~
今回はPlaneにオリジナルの当たり判定を作成し、
VRCInstantiateを使用して、道の動的生成を行います。

参考文献

やぎりさんのUdonSharpコード走り書きメモ・・・VRCInstantiate

やり方

最初にスポーンするPlaneの横に、これからどんどんコピーしていく予定のPlaneを置きます。
無題.png
ここにUdonBehaviourをつけて、UdonSharpを適用します。
そして次のコードを作成します。

Floor.cs
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using UnityEngine.UI;

public class Floor : UdonSharpBehaviour
{
    public GameObject prefab;
    public Text debugText;
    bool is_stillGiveBirth = false;
    void Update()
    {
        var player = Networking.LocalPlayer;
        if (player != null)//Unityの再生ボタンで実行すると変数がnullになるらしいよ
        {
            //playerの位置を取得(位置は頭の位置を使用)
            var headData = player.GetTrackingData(VRCPlayerApi.TrackingDataType.Head);

            debugText.text = string.Format("Head-Pos: {0}\r\n", headData.position.ToString());
            if (is_In(headData.position) && is_stillGiveBirth == false)
            {
                //当たり判定があり、まだPlaneを生成していない場合、Planeを生成する。
                var go = VRCInstantiate(prefab);
                go.GetComponent<Transform>().position = new Vector3(0.0f, 0.0f, prefab.transform.position.z + 2.0f);
                is_stillGiveBirth = true;
            }
        }
    } 
    //入力されたVector3(座標)が自身の中にあるかどうかを判定する
    //使用するのはx,zの2次元座標のみ
    private bool is_In(Vector3 pos)
    {
        float myX = this.transform.position.x;
        float myZ = this.transform.position.z;
        float scaleX = 5.0f*this.transform.localScale.x;
        float scaleZ = 5.0f*this.transform.localScale.z;
        //x chexk
        if(myX - scaleX < pos.x && pos.x < myX + scaleX)
        {
            //z check
            if (myZ - scaleZ < pos.z && pos.z < myZ + scaleZ)
            {
                debugText.text = string.Format("ON: x{0}, z{1}, sx{2}, sz{3}\r\n", myX, myZ, scaleX, scaleZ);
                return true;
            }
        }
        return false;
    }
}

設計方針としては以下の通り。
1.プレイヤーの座標を得る
2.自身(Plane)の座標と幅・高さを考慮したものと比較して当たり判定をとる
3.当たる場合、自身をクローンして先の座標に生成する。
4.何度も生成しないようにフラグを立てる

難しくないのだけど、当たり判定を使わずにコライダーを使ったらどうか?とか
クローンに使用する関数は何を使うべきか?とか
幅と高さはscaleを使ってるけど、絶対座標系との対応が取れなくてどうしようとか
(今回は実験なのでマジックナンバーとしました)
そんなこんな考えていたら、5時間くらいかかっています。

知識がないところからスタートすると時間かかりますね。

課題

今回使用したVRCInstantiateは動機が取れないとのこと
(本当に非同期化は調べていない)
解決策を考えなくては・・・
一つ気になることといえば
黒鳥さんのUDONメモによると・・・

VRCInstantiateのあれこれ(2020/04/11現在)
現在同期的にインスタンス化を行う方法がない?
インスタンス化したオブジェクトではUdonBehaviourが死ぬ。
SendCustomNetworkEventで同期的にインスタンス化出来ているようにみえるが、PickupとUdonBehaviourが死ぬ。
プレハブの座標とは違う場所からインスタンス化される。

とあり、インスタンス化したPlaneでUdonBehaviourが動かないことが報告されており、
今回の実験とは結果が違うので、慎重に調査をしないといけません。
今回の実験はローカル上でのテストなのでVRChatにアップすると挙動が違うかもしれない。

後日談

Udonが抱えているバグとして、インスタンス化したオブジェクトでは”時々”UdonBehaviorを失ったり、トリガーが機能しなくなるとのこと。
今回の記事で作成したものは、インスタンスがどんどん次のインスタンスを作成していくコードとなっていたので現時点(2020/4/27)では良くない設計例ですね。

3
2
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
3
2