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

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

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

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

0回答

1586閲覧

if文を使って、クリック時に親オブジェクト位置に子オブジェクトを移動

F.Child

総合スコア12

C#

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

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/07/16 06:50

前提・実現したいこと

UnityでC#scriptでの動作付け関する質問です。VR(FOVE)に接続しての使用を想定しています。
Unityとプログラミング両方初心者なため、うまく状況をお伝えできているか分かりませんが、説明不足な場合はご指摘をお願い致します。

【やりたいこと】

  1. 最初のクリックで、Maincameraを中心とした球上の特定の場所に、ランダムでMaincameraの子オブジェクトとして弾を生成し、かつMaincameraに向かって移動させる
  2. その後のクリックで、弾を停止させ、その時の弾とMaincameraの距離を測る
  3. その後のクリックで、弾を消す

→その後のクリックはまた1.に戻る

【現在の作成状況】
Unity上
・弾のPrefabの作成
・Maincameraの設置

Maincameraにアタッチするscript
Start
・「球上の特定の場所」をvector3型の配列("creatPoints")としてまとめる
・配列の中の順序をシャッフルする(unityスクリプトリファレンスの"リストをシャッフルする"を参照)

Update
if文を使い、クリック時の各動作を指定
[1回目クリック時]
・シャッフルした配列i番目の座標に弾を生成
・弾の親オブジェクトをMaincameraに指定
・Maincameraの位置取得
・Movetowardsで弾をMaincameraまで移動

[2回目クリック時]
・弾の移動を停止
・弾とMaincameraの距離を算出

[3回目クリック時]
・弾を消す

※以降のクリック時の挙動は、1回目クリック時 → 2回目クリック時 → 3回目クリック時 → 1回目クリック時 ... と繰り返していきます。

発生している問題

エラー表示は出ていないのですが、2回目のクリックの際、弾がわずかに動くだけでうまく移動してくれません。
その他の、1回目クリック時の挙動「Maincameraを中心とした球上のランダム位置での弾の生成」と3回目クリック時の挙動「弾の消去」は問題なく行われているようです。

該当のソースコード

Maincameraにアタッチしているscript

C#

1public class Move : MonoBehaviour 2{ 3 public GameObject Gun; 4 public GameObject MainCamera; 5 GameObject GunClone; 6 public List<GameObject> GunList = new List<GameObject>(); 7 private int flug = 0; 8 private int j = 0; 9 Vector3[] creatPoints = new Vector3[62]; 10 Vector3 targetPosition; 11 12 // Use this for initialization 13 void Start() 14 { 15 //※以下のような座標の指定をcreatPoints[0]~[61]まで書いていますが、長いのでここでは省略します。 16 17 //creatPoints[i] = new Vector3( 18 //半径 * Mathf.Cos(φ * Mathf.Deg2Rad) * Mathf.Sin(θ * Mathf.Deg2Rad), 19 //半径 * Mathf.Sin(φ * Mathf.Deg2Rad) 20 //半径 * Mathf.Cos(φ * Mathf.Deg2Rad) * Mathf.Cos(θ * Mathf.Deg2Rad)); 21 22 23 //シャッフル内容の確認作業 24 VeiwcreatPoints(); 25 Shuffle(); 26 VeiwcreatPoints(); 27 } 28 29 void Shuffle() //配列の中身をシャッフル 30 { 31 Debug.Log("Shuffle"); 32 for (int i = 0; i < creatPoints.Length; i++) 33 { 34 Vector3 temp = creatPoints[i]; 35 int randomIndex = Random.Range(0, creatPoints.Length); 36 creatPoints[i] = creatPoints[randomIndex]; 37 creatPoints[randomIndex] = temp; 38 } 39 } 40 41 void VeiwcreatPoints() //シャッフル内容確認のためのデバッグメソッド 42 { 43 for (int i = 0; i < creatPoints.Length; i++) 44 { 45 Debug.Log(creatPoints[i]); 46 } 47 } 48 49 // Update is called once per frame 50 void Update() 51 { 52 MainCamera = transform.root.gameObject; //MainCameraが一番上の階層のオブジェクト 53 54 if ((Input.GetMouseButtonDown(0)) && (this.flug == 0)) //マウス押下かつflug=0の時、弾の生成。その後flugを1に。 55 { 56 GunClone = (GameObject)Instantiate(Gun, this.transform.localPosition, Quaternion.identity); 57 GunClone.transform.parent = MainCamera.transform; 58 MainCamera.transform.localPosition = new Vector3(0, 0, 0); 59 GunClone.transform.localPosition = creatPoints[j]; 60 GunClone.transform.position = Vector3.MoveTowards(GunClone.transform.localPosition, MainCamera.transform.localPosition, 10f * Time.deltaTime); 61 this.flug = 1; 62 } 63 64 else if ((Input.GetMouseButtonDown(0)) && (this.flug == 1)) //マウス押下かつflug=1の時、弾を止め、距離の算出。その後flugを2に。 65 { 66 Time.timeScale = 0; 67 Vector3 GunClonePoint = GameObject.Find("Gun(Clone)").transform.position; 68 Debug.Log("Distance"); 69 Debug.Log(Vector3.Distance(GunClonePoint, targetPosition)); 70 this.flug = 2; 71 } 72 73 else if ((Input.GetMouseButtonDown(0)) && (this.flug == 2)) //マウス押下かつflug=2の時、弾を消す。その後jに+1する。 74 { 75 Destroy(this.GunClone); 76 this.flug = 0; 77 j++; 78 } 79 80 } 81}

試したこと

弾のPrefabに「移動のメソッドを描いたscript」を直接アタッチし、Maincameraにアタッチするscript内にはその弾Prefabの生成だけを記述してみましたが、前述と同様の結果になりました。

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

Unity5.6.3

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

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

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

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

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

sakura_hana

2019/07/16 07:09

2回目のクリック時(「this.flug==1」の時)、弾の位置を取得すること以外していないので停止も移動もしない気がするのですが。(距離も取ってはいるがDebug.Logしかしていない)
F.Child

2019/07/16 07:38 編集

早速にご返信ありがとうございます。 一応自分の解釈では、 (「this.flug == 0」の時の)GunClone.transform.position = Vector3.MoveTowards(GunClone.transform.localPosition, MainCamera.transform.localPosition, 10f * Time.deltaTime); で移動をして、 (「this.flug == 1」の)Time.timeScale = 0; でその移動を止める、 というイメージでした。
sakura_hana

2019/07/16 07:53

それで言うと、「this.flug == 0」の時、移動した直後に「this.flug = 1」しているので移動は実質1フレームしか起こっていないはずです(次フレームではこのifから外れるから)。これは想定通りの動作ですか? というかやりたいことでは「その後のクリックで、弾を停止させ、その時の弾とMaincameraの距離を測る」とあり、発生している問題では「2回目のクリックの際、弾がわずかに動くだけでうまく移動してくれません」とあります。結局何がしたくて、今どう動いているのでしょう?(停止&距離計測なら今のコードでもいいのでは?)
F.Child

2019/07/16 08:03

すいません、「2回目のクリックの際~」というのが間違えていました。正しくは「1回目のクリックの際にうまく移動しない」です。大変失礼いたしました。 おそらく問題があったのは、ご指摘くださった次フレームではこのifから外れるために1フレーム分の移動しかで来ていないというところじゃないか思います。 やりたいことは、 1回目のクリックで、弾が生成されると同時に移動を開始する 2回目のクリックで、移動している弾が停止する(+その時の距離をDebug.Logで表示する) です。
F.Child

2019/07/16 08:08

現状の動きは以下の通りです、 1回目のクリック → 弾の生成はされるが、止まったまま動かない 2回目のクリック → 止まったまま(Debug.Logは表示されるが動いていないため常に球の半径が表示される) 3回目のクリック → 弾が消える
sakura_hana

2019/07/16 08:25

そうですね。今のコードは「クリックした時(1フレーム間)かつthis.flug==0の時」しか移動しないので、移動するコードを「this.flug==1の時」のみのif文に入れれば動くのではと思います。 なお些細な問題&現状は影響が無いかもですが、 GunClone.transform.position = Vector3.MoveTowards(GunClone.transform.localPosition, MainCamera.transform.localPosition, 10f * Time.deltaTime); このコード、「GunCloneのローカル座標からMainCameraのローカル座標へ少し進んだ座標を、GunCloneのワールド座標として指定」という意味なので、変な動きするかもです。 (positionとlocalPositionのどちらかに統一すべきかと。あとMainCamera.transform.localPositionはMainCameraが何かの子オブジェクトになっていると想定したのと違う位置を取るかもしれないのでこちらも注意)
F.Child

2019/07/16 08:57

何度もすみません、改善方法に関しての理解がまだ追いついていなくて、、”移動するコードを「this.flug==1の時」のみのif文に入れれば”についてもう少しだけ補足して頂きただければ幸いです。 これは現状、 if (クリック && this.flug==0) {生成、移動 }else if (クリック && this.flug==1) {停止、距離 }else if (クリック && this.flug==2) { 消す } となっているのを、 if (クリック && this.flug==0) {生成、移動 } if (クリック && this.flug==1) {停止、距離 } if (クリック && this.flug==2) { 消す } というように分けて書くということでしょうか? よろしくお願いいたします。 些細な問題に関してのご指摘もありがとうございます。positionの統一、修正してみます。
sakura_hana

2019/07/16 09:14

if (クリック && this.flug==0){ 生成、this.flug=1 } else if (クリック && this.flug==1){ 停止※、距離、this.flug=2 } else if (クリック && this.flug==2){ 消す、this.flug=0 } if (this.flug==1){ 移動 } こんな感じになると思います。 なお※を付けた停止の部分ですが、対象オブジェクトを移動させない(=停止する)のが目的なだけなら「Time.timeScale=0;」は要りません(上記なら、this.flugが1ではなくなった時点で移動はしなくなる為)。 Time.timeScale=0は「Unity上の時間を停止」のようなものなので、実行すると他のオブジェクトも止まります(それを希望しているならこのままでいいですが)。
F.Child

2019/07/16 09:28

なるほど!クリックなしで「this.flug=1」となった時点で移動するようにして、移動部分だけ独立させればいいのですね。 こちらの型で書き直してチャレンジしてみます! ※Unity上の全体の時間を止める必要はないので、Time.timeScale=0の部分は削ります。 丁寧にご対応していただいてありがとうございます。ネットを調べながらずっと一人で格闘していたので、アドバイス頂けて本当に良かったですm(__)m 後ほどまた改善後のご報告できればと思います。
F.Child

2019/07/17 08:31 編集

これまでのアドバイスをもとに書き直してみた。 ①「移動するコード」の移動と、②座標系をpositionに統一 を試みたのですが、まだ弾が動いてくれません、、 問題点などご指摘いただければ幸いです。 以下、修正後のscript(update部分)です。 void Update() { MainCamera = transform.root.gameObject; if ((Input.GetMouseButtonDown(0)) && (this.flug == 0)) { GunClone = (GameObject)Instantiate(Gun, this.transform.localPosition, Quaternion.identity); GunClone.transform.parent = MainCamera.transform; MainCamera.transform.localPosition = new Vector3(0, 0, 0); GunClone.transform.localPosition = creatPoints[j]; this.flug = 1; } else if ((Input.GetMouseButtonDown(0)) && (this.flug == 1)) { this.flug = 2; Vector3 GunClonePoint = GameObject.Find("Gun(Clone)").transform.position; Debug.Log("Distance"); Debug.Log(Vector3.Distance(GunClonePoint, targetPosition)); } else if ((Input.GetMouseButtonDown(0)) && (this.flug == 2)) { Destroy(this.GunClone); this.flug = 0; j++; } if (this.flug == 1) { float step = speed * Time.deltaTime; GunClone.transform.position = Vector3.MoveTowards(GunClone.transform.position, target.position, step); } } 追記: MoveTowards内の”target”はpublic classで、 public Transform target; と宣言し、unity editorのインスペクター上でtargetの欄にMaincameraをドラッグ&ドロップしています。
sakura_hana

2019/07/17 08:31

まずspeedが0ではないか確認を。(0だとMoveTowardsが現在地を指すのでその場に止まり続ける) あとは GunClone.transform.position = Vector3.MoveTowards(〜 の前の行に Debug.Log(GunClone.transform.position+" "+target.position); と追記して値の推移を確認してみてください。
F.Child

2019/07/17 09:10

speedはUnityEditor上で”10”と設定しています。(弾は生成時、カメラとの距離が50なので、5秒間でカメラまで移動という設定です) Debug.Log(GunClone.transform.position+" "+target.position); の実行結果は下記のようになりました。画像が貼れないのでリンクで失礼します。 弾の位置は全く動いていないようです。 https://4.gigafile.nu/0724-9c05f0a66d0c71bb6c1b067b5823c36f 3つの警告文はどうやらこの行↓を指しているようなのですが、Gunに関してもUnityEditor上で弾のPrefabをGunの欄に設定はしています。 GunClone = (GameObject)Instantiate(Gun, this.transform.localPosition, Quaternion.identity);
sakura_hana

2019/07/17 11:31

これで動きそうなものですが、疑問ですね。 警告文は「オブジェクトに付いたスクリプトが消えてる」って意味なので原因を確認してください。 (多分Gunプレハブに付いてるスクリプトが消えてる) http://tsubakit1.hateblo.jp/entry/2016/10/06/232628 こっちが影響している可能性もあるので先に警告が消えるよう直してください。 (ちなみにGunにオブジェクトに付いているスクリプトが移動を打ち消してたりしませんよね?)
F.Child

2019/07/17 14:19

今Gunプレハブにスクリプトはつけていないのですが、見てみたところ、GunプレハブにScriptのComponentのみが残されたままになっていました。(いろいろ試しているときにscriptは消したけどScriptのComponentを削除し忘れていたのかと、、) これを削除したところ警告文は消えました。 弾はまだ動かないので、URLのページも参考にミスがないか今一度確認してみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問