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

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

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

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

Q&A

解決済

1回答

1870閲覧

Unity 指定した座標をオブジェクトが通過する

zexcy

総合スコア13

C#

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

0グッド

1クリップ

投稿2018/09/12 09:50

前提・実現したいこと

現在、対象のオブジェクトを指定した座標を移動させるといったスクリプトを書いています。
目的としては、現実場面のボールの動きを測定し、その動きをUnity上で表現することです.
スクリプトは、座標を一つ一つ手入力し、for文を使用して順番にその座標に移動させれば可能かと考えて作成いたしました。
下記に示してある座標は動作確認のために暫定的に入力したものです。

発生している問題・エラーメッセージ

上述したようにスクリプトを作成したところ、座標を一つ一つ通過するといった感じではなく、最終的に指定している座標付近へ
瞬間移動をしてしまうといった問題が生じています。

該当のソースコード

using System.Collections; using System.Collections.Generic; using UnityEngine; public class move_test : MonoBehaviour { public Vector3 [] pos; Vector3 pos1 = new Vector3(-11f, 0.15f, 1f); Vector3 pos2 = new Vector3(-12f, 0.15f, 1f); Vector3 pos3 = new Vector3(-11.5f, 0.15f, 1f); Vector3 pos4 = new Vector3(-11f, 0.15f, 1f); Vector3 pos5 = new Vector3(-10.5f, 0.15f, 1f); Vector3 pos6 = new Vector3(-10f, 0.16f, 1f); Vector3 pos7 = new Vector3(-9.5f, 0.16f, 1f); Vector3 pos8 = new Vector3(-9f, 0.16f, 1f); Vector3 pos9 = new Vector3(-8.5f, 0.17f, 1f); Vector3 pos10 = new Vector3(-8f, 0.17f, 1f); Vector3 pos11 = new Vector3(-7.5f, 0.17f, 1f); Vector3 pos12 = new Vector3(-7f, 0.17f, 1f); Vector3 pos13 = new Vector3(-6.5f, 0.18f, 1f); Vector3 pos14 = new Vector3(-6f, 0.18f, 1f); Vector3 pos15 = new Vector3(-5.5f, 0.18f, 1f); Vector3 pos16 = new Vector3(-5f, 0.19f, 1f); Vector3 pos17 = new Vector3(-4.5f, 0.19f, 1f); Vector3 pos18 = new Vector3(-4f, 0.19f, 1f); Vector3 pos19 = new Vector3(-3.5f, 0.19f, 1f); Vector3 pos20 = new Vector3(-3f, 0.19f, 1f); Vector3 pos21 = new Vector3(-2.5f, 0.2f, 1f); Vector3 pos22 = new Vector3(-2f, 0.2f, 1f); Vector3 pos23 = new Vector3(-1.5f, 0.2f, 1f); Vector3 pos24 = new Vector3(-1f, 0.2f, 1f); Vector3 pos25 = new Vector3(-0.5f, 0.19f, 1f); Vector3 pos26 = new Vector3(0f, 0.19f, 1f); Vector3 pos27 = new Vector3(0.5f, 0.18f, 1f); Vector3 pos28 = new Vector3(1f, 0.17f, 1f); Vector3 pos29 = new Vector3(1.5f, 0.17f, 1f); Vector3 pos30 = new Vector3(2f, 0.16f, 1f); // Use this for initialization void Start () { int sum = 0; for (int i = 0; i < 30; i++) ; sum = sum + 1; pos = new Vector3[30]; Vector3 ballpos = pos[sum]; this.gameObject.transform.position = new Vector3(ballpos.x, ballpos.y, ballpos.z); } // Update is called once per frame void Update () { } }

試したこと

補足情報(FW/ツールのバージョンなど)

Unity 2018.2.7.f1

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ご質問のコードは、Start()の中に全てのコードを記述しています。
しかしStart()はコンポーネントが有効になった時に、「1度だけ」呼び出される初期化関数です。
すなわちStart()の中でfor文をまわしても、初期化時に全てのforが回ってしまうため、初期化が終了して画面に反映される時には最後の状態しか表示されません。

そこで、画面更新のたびに呼び出されるUpdate()関数を利用します。
Updateは実行中に何度も呼びだされるため、この中で順次座標を変化させていけば、移動しているように見えるハズです。そのためこのUpdate()関数の中で配列のインデックスをオブジェクトのpositionへ反映させると同時に配列のインデックスをインクリメントします。

という事で、以下のようにコードを修正してみました。

csharp

1public class move_test : MonoBehaviour 2{ 3 private Vector3[] pos = new Vector3[] 4 { 5 new Vector3(-11f, 0.15f, 1f), 6 new Vector3(-12f, 0.15f, 1f), 7 new Vector3(-11.5f, 0.15f, 1f), 8 new Vector3(-11f, 0.15f, 1f), 9 new Vector3(-10.5f, 0.15f, 1f), 10 new Vector3(-10f, 0.16f, 1f), 11 new Vector3(-9.5f, 0.16f, 1f), 12 new Vector3(-9f, 0.16f, 1f), 13 new Vector3(-8.5f, 0.17f, 1f), 14 new Vector3(-8f, 0.17f, 1f), 15 new Vector3(-7.5f, 0.17f, 1f), 16 new Vector3(-7f, 0.17f, 1f), 17 new Vector3(-6.5f, 0.18f, 1f), 18 new Vector3(-6f, 0.18f, 1f), 19 new Vector3(-5.5f, 0.18f, 1f), 20 new Vector3(-5f, 0.19f, 1f), 21 new Vector3(-4.5f, 0.19f, 1f), 22 new Vector3(-4f, 0.19f, 1f), 23 new Vector3(-3.5f, 0.19f, 1f), 24 new Vector3(-3f, 0.19f, 1f), 25 new Vector3(-2.5f, 0.2f, 1f), 26 new Vector3(-2f, 0.2f, 1f), 27 new Vector3(-1.5f, 0.2f, 1f), 28 new Vector3(-1f, 0.2f, 1f), 29 new Vector3(-0.5f, 0.19f, 1f), 30 new Vector3(0f, 0.19f, 1f), 31 new Vector3(0.5f, 0.18f, 1f), 32 new Vector3(1f, 0.17f, 1f), 33 new Vector3(1.5f, 0.17f, 1f), 34 new Vector3(2f, 0.16f, 1f), 35 }; 36 37 private int AnimIndex = 0; 38 39 // Use this for initialization 40 void Start() 41 { 42 this.gameObject.transform.position = pos[AnimIndex++]; 43 } 44 45 // Update is called once per frame 46 void Update() 47 { 48 if(AnimIndex < pos.Length) 49 { 50 this.gameObject.transform.position = pos[AnimIndex++]; 51 } 52 } 53}

投稿2018/09/13 04:04

編集2018/09/13 11:41
TakafumiYuasa

総合スコア124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

zexcy

2018/09/13 09:48

回答していただきありがとうございます。 早速試してみたところ、瞬間移動することなく、移動いたしました。 これはVector3の空箱を用意して、newを順番に配列したというイメージでいいのでしょうか? また、動きに関して少し違和感が生じたので以下のようなコードを加えて,なかみの確認をしてみました. void Start() { this.gameObject.transform.position = pos[AnimIndex++]; Debug.Log(pos[1]); Debug.Log(pos[2]); Debug.Log(pos[3]); Debug.Log(pos[4]); Debug.Log(pos[10]); } すると,デバックの内容が、以下のようになりました. (-12.0, 0.2, 1.0) UnityEngine.Debug:Log(Object) move_test:Start() (at Assets/move_test.cs:50) (-11.5, 0.2, 1.0) UnityEngine.Debug:Log(Object) move_test:Start() (at Assets/move_test.cs:51) (-11.0, 0.2, 1.0) UnityEngine.Debug:Log(Object) move_test:Start() (at Assets/move_test.cs:52) (-10.5, 0.2, 1.0) UnityEngine.Debug:Log(Object) move_test:Start() (at Assets/move_test.cs:53) (-7.5, 0.2, 1.0) UnityEngine.Debug:Log(Object) move_test:Start() (at Assets/move_test.cs:54) おそらくですが、1つ目の座標が反映されており、2つ目,3つ目は固定値になっているみたいです. この点に関しては、理由が不明ですので,もしご回答いただけると大変助かります.
ooa

2018/09/13 10:03

この場合、Start()は初めに1度しか呼ばれないので、Start()の中で座標を変化させても、刻々とその変化を描画することはなく 最後の座標になってから描画されます(テレポートみたいになる理由です) forのスコープの切り方も間違っていますので、ご確認ください。 gesyutapoさんの解答のように、Update()にて、毎回インデックスをインクリメントして、点を一つずつ推移させるのが良いでしょう。 また上記のご質問ですが、配列は[0]から始まるので、このログですと、2点めからの座標を表示しています。 また、0.15は丸められて0.2と表示されているようです。
TakafumiYuasa

2018/09/13 11:29

回答を記述した時ちょっと時間が無く、説明が無さ過ぎてすみませんでした。 また、ooaさん補足説明ありがとうございます。 配列の件ですが、回答のコードでは配列の初期化を行い、領域の確保と同時に値も代入しています。 zexcyさんのご質問のコードでは、配列の領域確保は行われておりますが、値の代入が行われていないため、配列posの中身は全てデフォルト値のVector3で埋められております。(x=0, y=0, z=0) そのため、ご質問のコードを実行した時、恐らくオブジェクトは(x=0, y=0, z=0)の場所に表示されていたのではないかと思います。zexcyさんご自身でも質問文で「最終的に指定している"座標付近"」とおっしゃっているので、最終的に指定している座標そのものではない事に気づかれているかと思います。 また、デバッグメッセージの件ですが、ooaさんのおっしゃる通り、四捨五入されて表示されています。 これは Debug.Log(pos[1]); と記述した時、実際は Debug.Log(pos[1].toString()); というコードと等価であり、Vector3.toString()は値を四捨五入して表示する仕様になっているようです。 四捨五入せずに小数点第二位まで表示したい場合は Debug.Log(pos[1].toString("F2")); などとすると良いと思います。
zexcy

2018/09/13 12:04

ooaさん,gesyutapoさん,ご丁寧な指摘をどうもありがとうございました. また,確認してみたところ,gesyutapoさんのおっしゃる通り,原点にとどまっていました. 実の所,Unityのプログラミングは初めて1か月ほどなので,お二人の専門用語(インクリメントや領域の確保などなど・・)すらわからないぐらい初心者ですが,なんとなく理解できたような気がします. 今は座標を一つ一つ入力していますが,今後はエクセルのデータを読み込んできて反映させる. もしくは,元データから動きの近似式を算出し,その式に時間経過を代入するといった方法になっていくかと思います. 前者の場合は,今回の回答がかなり生かせるのかなと考えていますが,後者の場合ですと,今回のスクリプトとは違うものになってしまうかもしれません。その場合は申し訳ありません。 しかしながら,後者は数学や物理の知識がたくさんいるかと思いますので,かなり時間がかかるため、すぐには無理かと思います. 今後も困った際にはご指摘など頂ければ幸いです.本当にありがとうございました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問