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

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

新規登録して質問してみよう
ただいま回答率
87.20%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

解決済

【Unity2D】TouchPhase.Endedとそれ以外ではAddForceの結果が異なることへの疑問

funyao
funyao

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

1回答

0評価

0クリップ

10閲覧

投稿2019/04/13 16:00

編集2022/01/12 10:58

疑問

 Unity2Dにて「ボールをタッチでのベクトル入力とAddForceで投射する」スクリプトを作成中、「TouchPhase.Endedとそれ以外ではAddForceの結果が異なること」で制作がつまづきました。

“TouchPhase.EndedではAddForceの働きが変化するのか? それは何に由来するのか?”
という疑問を解消したく、この質問を投稿しました。

###この投稿までの経緯
現在、「ボールをタッチでのベクトル入力とAddForceで投射する」、玉入れのようなゲームを制作中です。
(操作感覚としては“アングリーバード”に近いものと考えています)
その中で「ボールが投射される軌道予測線が表示されていた方がよい」とまず考えました。まず最初は投射のベクトルと落下をLineRendererで描写することを考え、実装しました。しかしさらに進んで、「仮のボール(Ghost)が投射される軌道を再現してみるのはどうか」と考え、このスクリプトの作成に入りました。

ところが、Endedでは想定通りにボールを投射していた命令文が、その他の状態では動かず(投射されずに射出地点からポトリと落ちる)、一度詰まりました。そこで手当たり次第に方法を試し、AddForceのモードをImpulseに指定したところ、想定通りの動作をしました。

ここで確かに想定通りの動作は達成したのですが、
「そもそも何故トラブルになったのか? Endedのみではなぜ今までトラブルが起きなかったのか?」
が理解できておらず、今後の妨げになるのではと心配しています。

###問題になったAddForce(本件のための実験用スクリプト)
疑問の元となった内容を実験用にまとめ直しました。
問題となるAddForceの関数は比較のために最後尾にまとめています。

C#

using System.Collections; using System.Collections.Generic; using UnityEngine; public class TestAddForce : MonoBehaviour { //タッチ開始点と終了点の取得 Vector2 startP; Vector2 MoveP; Vector2 EndP; //なぜかMoved・Sta中はボールの挙動が強くでてしまう。それを抑えるために極小倍率を掛ける。 //当環境では“何故か”0.02倍にすることで動作が一致する。 //当環境FixedTimestep=0.02、と関係あるのかな…? public float power = 0.02f; Vector2 MovedVector; //予測用IsTrigger=Onボールと実体ボール //テスト環境では同一プレハブでも試行しました public GameObject GhostBallpb; public GameObject Ballpb; void Start () { //無用な連射を防ぐため、前のボールが地面に落ちたことの確認bool DestroyGroundPlus.PreBall = true; } void Update () { if (Input.touchCount == 1) { Touch T = Input.touches[0]; if (T.phase == TouchPhase.Began) { startP = T.position; } if (T.phase == TouchPhase.Moved) { MoveP = T.position; MovedVector = (startP - MoveP) * power; //power=0.02f if (DestroyGroundPlus.PreBall == true) { MovedShoot(MovedVector); //実験用関数、その2 //Debug.Log("Moved " + MovedVector); } } if (DestroyGroundPlus.PreBall == true) { UpdateShoot(MovedVector); //実験用関数、その1 } if (T.phase == TouchPhase.Stationary) { if (DestroyGroundPlus.PreBall == true) { StayShoot(MovedVector); //実験用関数、その3 } } if (T.phase == TouchPhase.Ended) { EndP = T.position; Vector2 EndedVector = (startP - EndP) * 1; //power倍率1倍 EndedShoot(EndedVector); //実験用関数、その4 } } } void UpdateShoot(Vector2 Vec) { GameObject Ghost = Instantiate(GhostBallpb, transform.position, transform.rotation); //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec); //ダメ 自由落下 //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Force); //ダメ 自由落下 Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Impulse); //投射成功 //無用な連射を防ぐため、前のボールが地面に落ちたことの確認bool DestroyGroundPlus.PreBall = false; } void MovedShoot(Vector2 Vec) { GameObject Ghost = Instantiate(GhostBallpb, transform.position, transform.rotation); //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec); //ダメ 自由落下 //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Force); //ダメ 自由落下 Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Impulse); //投射成功 DestroyGroundPlus.PreBall = false; } void StayShoot(Vector2 Vec) { GameObject Ghost = Instantiate(GhostBallpb, transform.position, transform.rotation); //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec); //ダメ 自由落下 //Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Force); //ダメ 自由落下 Ghost.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Impulse); //投射成功 DestroyGroundPlus.PreBall = false; } void EndedShoot(Vector2 Vec) { GameObject Ball = Instantiate(Ballpb, transform.position, transform.rotation); Ball.GetComponent<Rigidbody2D>().AddForce(Vec); //投射成功 //Ball.GetComponent<Rigidbody2D>().AddForce(Vec, ForceMode2D.Force); //投射成功 //Ball.GetComponent<Rigidbody2D>().AddForce(Vec, mode: ForceMode2D.Impulse); //ベクトル方向の彼方へぶっ飛ぶ パワー倍率1倍のせい? } }

###疑問のまとめ直し
『TouchPhase.Endedとそれ以外ではAddForceの結果が異なること』の原因を学習したいです。
Ⅰ:Ended内では“AddForce()”の働きがその他と異なる
Ⅱ:Ended内でも、“AddForce(Vec, mode: ForceMode2D.Impulse)”の際はボールがぶっ飛ぶ
(Ⅲ:本件とはズレるが、なぜ命令位置でAddForceの力の掛かり具合が変化するのだろう…?)

「バッカだなあ、それはかくかくしかじかだから」
「ここを読んで勉強しろや。 “https://~~”」
など、ご教授いただきたいです。

良い質問の評価を上げる

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

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

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

気になる質問をクリップする

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

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

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

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

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

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

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

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。