質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.21%

velocityでの次の到達地点

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,031

tkmnusr

score 302

 前提・実現したいこと

transform系での移動は、Mathf.Clampを使えば移動制限できるみたいですが、
velocityでの移動はどのように制御すれば移動制限できるのでしょうか?
ご教示お願いします。

 該当のソースコード

    void FixedUpdate(){
        rb.velocity = this.transform.right * speed;
    }

 試したこと

transform系での移動は、こちらのサイトのように、
Mathf.Clampを使えば移動制限できることがわかりました。

    // 移動量を加える
    pos += direction * spaceship.speed * Time.deltaTime;

    // プレイヤーの位置が画面内に収まるように制限をかける
    pos.x = Mathf.Clamp (pos.x, min.x, max.x);
    pos.y = Mathf.Clamp (pos.y, min.y, max.y);

velocityの場合でも、Mathf.Clampを使って移動制限できるのでしょうか?
可能であれば、Mathf.Clampを使った移動制限を知りたいですが、
不可能であれば、velocityでの次の到達点が指定範囲内ならば、
移動するといった制御にしたいです。

    void FixedUpdate(){
        if(velocityでの次の到達点<max.x){
            rb.velocity = this.transform.right * speed;
        }
    }

妥協案として、「移動前に制限」ではなく、「移動後に調整して制限」を考えてみたのですが、
下記のコードでも、移動制限されませんでした。
下記コードが意図通りにいかない理由もわかりませんが、できればこのようなコードではなく、
「移動前に制限」させたいです。

    void FixedUpdate(){        
        rb.velocity = this.transform.right * speed;
        if(this.transform.position.x > max.x){
            Vector3 limit = new Vector3(max.x, this.transform.position.y, this.transform.position.z);
            this.transform.position = limit;
        }
    }

 追記。

    void Update () {
        Vector3 viewport = Camera.main.WorldToViewportPoint(this.transform.position);
        Vector3 viewmin = new Vector3(0.0f, 0.0f,viewport.z);
        Vector3 viewmax = new Vector3(1.0f, 1.0f,viewport.z);
        min = Camera.main.ViewportToWorldPoint(viewmin);
        max = Camera.main.ViewportToWorldPoint(viewmax);

    }

    void FixedUpdate(){

        Vector3 pos = this.transform.position + (this.transform.right * speed);
        pos.x = Mathf.Clamp(pos.x, min.x, max.x);

        rb.velocity = pos - this.transform.position; 

 追記②

float speed = 2.0f;
Vector3 min;
Vector3 max;

void Update () {
    Vector3 viewport = Camera.main.WorldToViewportPoint(this.transform.position);
    Vector3 viewmin = new Vector3(0.0f, 0.0f,viewport.z);
    Vector3 viewmax = new Vector3(1.0f, 1.0f,viewport.z);
    min = Camera.main.ViewportToWorldPoint(viewmin);
    max = Camera.main.ViewportToWorldPoint(viewmax);
    Debug.Log(max);
}

void FixedUpdate(){

    Vector3 pos = this.transform.position + this.transform.TransformDirection(this.transform.right * speed);
    pos.x = Mathf.Clamp(pos.x, min.x, max.x);

    rb.velocity = transform.InverseTransformDirection(pos - this.transform.position); 
}

 追記③

    Vector3 max;

    void Start () {
        //空のゲームオブジェクトの位置に設定。
        max = go.transform.position;
    }

    void FixedUpdate(){

        Vector3 pos = this.transform.position + this.transform.TransformDirection(this.transform.right * speed);
        pos.x = Mathf.Clamp(pos.x, min.x, max.x);

        rb.velocity = transform.InverseTransformDirection(pos - this.transform.position); 
    }

イメージ説明

イメージ説明

 追記④

イメージ説明

    Vector3 min;
    Vector3 max;

    void Start () {
    }


    void Update () {
        Vector3 viewport = Camera.main.WorldToViewportPoint(this.transform.position);
        Vector3 viewmin = new Vector3(0.0f, 0.0f,viewport.z);
        Vector3 viewmax = new Vector3(1.0f, 1.0f,viewport.z);
        min = Camera.main.ViewportToWorldPoint(viewmin);
        max = Camera.main.ViewportToWorldPoint(viewmax);
    }


    void FixedUpdate(){

        Vector3 pos = this.transform.position + this.transform.TransformDirection(this.transform.right * speed);
        pos.x = Mathf.Clamp(pos.x, min.x, max.x);
        pos.z = Mathf.Clamp(pos.z, min.z, max.z);

        rb.velocity = transform.InverseTransformDirection(pos - this.transform.position); 

 追記⑤

    void Update () {
        Vector3 viewport = Camera.main.WorldToViewportPoint(this.transform.position);
        Vector3 viewmin = new Vector3(0.0f, 0.0f,viewport.z);
        Vector3 viewmax = new Vector3(1.0f, 1.0f,viewport.z);
        min = Camera.main.ViewportToWorldPoint(viewmin);
        max = Camera.main.ViewportToWorldPoint(viewmax);
    }


    void FixedUpdate(){

        Vector3 baseVelocity = this.transform.right * speed;
        Vector3 pos = this.transform.position + this.transform.TransformDirection(baseVelocity);
        pos.x = Mathf.Clamp(pos.x, min.x, max.x);

        Vector3 vel = transform.InverseTransformDirection(pos - this.transform.position);
        vel.z = vel.z * vel.x /baseVelocity.x;
        rb.velocity = vel;
    }

下の画像の位置で停止しました。ちょっと画面外に出てしまっています。
※移動時はy方向に動きません。
イメージ説明

 追記⑥

追記⑤の画像の停止位置とほぼ変わらない状態でした。

    void FixedUpdate(){

        Vector3 viewport = Camera.main.WorldToViewportPoint(this.transform.position);
        Vector3 viewmin = new Vector3(0.0f, 0.0f,viewport.z);
        Vector3 viewmax = new Vector3(1.0f, 1.0f,viewport.z);
        min = Camera.main.ViewportToWorldPoint(viewmin);
        max = Camera.main.ViewportToWorldPoint(viewmax);

        Vector3 baseVelocity = this.transform.right * speed;
        Vector3 pos = this.transform.position + this.transform.TransformDirection(baseVelocity);
        pos.x = Mathf.Clamp(pos.x, min.x, max.x);

        Vector3 vel = transform.InverseTransformDirection(pos - this.transform.position);
        vel.z = vel.z * vel.x /baseVelocity.x;
        rb.velocity = vel;
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

「速度」とは「時間あたりの移動量」です。
なので「現在地+velocity」が次の移動地点です。

よってMathf.Clampを使う場合もTransform系の移動と同じように出来ます。

    // 入力後の移動量を求める
    pos = this.transform.position + this.transform.right * speed;

    // プレイヤーの位置が画面内に収まるように制限をかける
    pos.x = Mathf.Clamp (pos.x, min.x, max.x);
    pos.y = Mathf.Clamp (pos.y, min.y, max.y);

    // 速度に反映
    rb.velocity = pos - this.transform.position;

妥協案のコードが上手くいかないのは、
「そのフレームでの位置」は決定されていても、「速度」がthis.transform.right * speedのままキープされているので、次のフレームでは移動が再開されるからだと思います。
例えるならエンジンがかかりっぱなしの車をある一点に置いても、次の瞬間には走り出して行ってしまうようなものです。
下記のようにすれば上手くいくのではないかと思います。

void FixedUpdate(){        
        if(this.transform.position.x > max.x){
            Vector3 limit = new Vector3(max.x, this.transform.position.y, this.transform.position.z);
            this.transform.position = limit;
            rb.velocity = Vector3.zero;
        } else {
            rb.velocity = this.transform.right * speed;
        }
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/22 20:29

    ご回答ありがとうございます。
    Update内の処理もFixedUpdateにまとめてみたのですが、結果はあまり変わらなかったです。
    ただ、maxのviewportを0.8f辺りに設定することで画面境界付近で停止してくれました。
    無理矢理な対処法にはなってしまいますが、これよりもキレイなコードで修正できる方法ってないですよね?

    キャンセル

  • 2018/06/25 15:43

    私もZ値が動くケースはやったことが無いので、近似値が出せたならそれで収めた方がいいかもしれないです。
    綺麗にまとめられずすみません。

    キャンセル

  • 2018/06/26 00:33 編集

    ご回答ありがとうございます。
    いえいえ、とんでもないです。
    ご教示くださり、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る