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

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

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

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

Unity

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

Q&A

解決済

1回答

734閲覧

Unity:オブジェクトのぐらつきを無くしたい

riririri_

総合スコア2

C#

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

Unity

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

0グッド

1クリップ

投稿2020/09/13 11:39

編集2020/09/13 12:00

Unityで2Dの積み上げゲームを作っているのですが、オブジェクトが乗った状態で土台を動かすとグラついてしまい、すぐに積み上げたものが崩れてしまいます。なので、グラつきをなくす(くっつく)ようにしたいのですが、上手くいきません。たくさん調べてみたのですが詳しく書いてあるようなものが見つからず困っている状況なので、解決方法をお教えいただけると幸いです。
ゲームとしては、「アイスクリーム積んでみた - カフェ https://unityroom.com/games/icecreamstack」こちらのようなものにしてみたいと思っています。

現在のオブジェクトと土台のコードは下記の通りです。

C#

1//オブジェクトのコード 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class ObjectController : MonoBehaviour 7{ 8 Rigidbody2D rigid; 9 // Start is called before the first frame update 10 void Start() 11 { 12 13 } 14 15 // Update is called once per frame 16 void Update() 17 { 18 //-5未満でオブジェクト削除 19 if(transform.position.y<-5) 20 { 21 Destroy(gameObject); 22 } 23 } 24 25 void OnCollisionEnter2D(Collision2D collision) 26 { 27 //床にぶつかったらオブジェクト削除 28 if (collision.gameObject.tag == "Floor") 29 { 30 Destroy(gameObject); 31 } 32 } 33 34 void OnCollisionStay2D(Collision2D collision) 35 { 36 //オブジェクト同士を親子関係に 37 if (collision.gameObject.tag == "Object"|| collision.gameObject.tag == "Object2" || collision.gameObject.tag == "Object3" ) 38 { 39 collision.gameObject.transform.SetParent(this.transform); 40 } 41 } 42 43 void OnCollisionExit2D(Collision2D collision) 44 { 45 //離れたら親子関係削除 46 if (collision.gameObject.tag == "Object" || collision.gameObject.tag == "Object2" || collision.gameObject.tag == "Object3" ) 47 { 48 collision.gameObject.transform.SetParent(null); 49 } 50 } 51} 52

C#

1//土台のコード 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.SceneManagement; 6 7public class PlayerController : MonoBehaviour 8{ 9 Rigidbody2D rigid; 10 11 // Start is called before the first frame update 12 void Start() 13 { 14 rigid = GetComponent<Rigidbody2D>(); 15 } 16 17 // Update is called once per frame 18 void Update() 19 { 20 if (Input.GetKey(KeyCode.LeftArrow)) 21 { 22 rigid.MovePosition(transform.position - transform.right * 3.5f * Time.deltaTime); 23 } 24 if (Input.GetKey(KeyCode.RightArrow)) 25 { 26 rigid.MovePosition(transform.position + transform.right * 3.5f * Time.deltaTime); 27 } 28 } 29 30}

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

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

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

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

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

guest

回答1

0

ベストアンサー

オブジェクトが乗った状態で、土台(床)を動かすと、上の物が落ちてしまうということですね。
マテリアルを作って摩擦(Fiction)を弄る方法がありますが(面倒くさい)、
衝突時に上に乗った要素を子オブジェクト、土台を親オブジェクトにするのはどうでしょうか。

void OnCollisionEnter(Collision collision) { transform.SetParent(collision.transform); }

検索方法としては「動く床」で検索すれば詳しく書いているものが出てくるかと思います。
余談ですが、本の場合「Unityではじめる2Dゲーム作り徹底ガイド」に「動く床」の記載があります(なんと「動く壁」についての記載もあります!!昔の本なので読みにくいですが……)。

投稿2020/09/15 15:36

436

総合スコア11

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

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

riririri_

2020/09/16 08:03

ご回答ありがとうございます。 前に下記のコードのように親子関係を使ってやってみたのですが、1番最初に落ちてきたものはしっかり土台にくっついて着いてきてくれるのですが、それ以降(最初に落ちてきたものの上に乗った場合)はくっついてくれず、その場に留まってしまい土台を動かすとそのまま下にすとんと落ちてしまう状況になってしまいました。 動く床についてもたくさん調べてはみたのですが、何段も重なっているものを動かすことについて書いているサイトは見当たりませんでした... 以下、親子関係を使って書いたコードです。 ``` //土台(プレイヤー) using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class PlayerController : MonoBehaviour { Rigidbody2D rigid; // Start is called before the first frame update void Start() { rigid = GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update() { if (Input.GetKey(KeyCode.LeftArrow)) { this.transform.Translate(-0.1f, 0.0f, 0.0f); } if (Input.GetKey(KeyCode.RightArrow)) { this.transform.Translate(0.1f, 0.0f, 0.0f); } } void OnCollisionEnter2D(Collision2D collision) { collision.gameObject.transform.SetParent(this.transform); } } ```
436

2020/09/17 02:36 編集

1.土台に下記メソッド追加 void OnCollisionExit2D(Collision2D collision) { collision.gameObject.transform.SetParent(null); } 2.落下物に下記スクリプト追加 public class apple : MonoBehaviour { public GameObject floor; void OnCollisionEnter2D(Collision2D collision) { collision.transform.parent = floor.transform; } void OnCollisionExit2D(Collision2D collision) { collision.transform.parent = null; } } 3.土台インスペクタのRigidbody2D/Constrains/FreezeRotatin/zにチェックを入れる 取り急ぎコメントのコードに対して、上記手順を行ったところ、 アイスクリームのような挙動が再現できました(雑ですが)。
riririri_

2020/09/17 09:48

ありがとうございます。感謝してもしきれません... 早速試してみたのですが、Unassigned ReferenceException: The variable floor of ObjectFixed has not been assigned. You probably need to assign the floor variable of the ObjectFixed script in the inspector.というエラーを吐いてしまいました... 追加のスクリプトは私が質問で載せたオブジェクトのコードと両方を落下物となるものにドラッグアンドドロップするということで合っていますでしょうか?私の勉強不足でご迷惑をおかけしてしまい誠に申し訳ございません。 最後に今使用しているスクリプト4つを載せますので、問題等ございましたら指摘していただけませんでしょうか... //土台(プレイヤー) using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement; public class PlayerController : MonoBehaviour { Rigidbody2D rigid; // Start is called before the first frame update void Start() { rigid = GetComponent<Rigidbody2D>(); } // Update is called once per frame void Update() { if (Input.GetKey(KeyCode.LeftArrow)) { this.transform.Translate(-0.1f, 0.0f, 0.0f); } if (Input.GetKey(KeyCode.RightArrow)) { this.transform.Translate(0.1f, 0.0f, 0.0f); } } void OnCollisionEnter2D(Collision2D collision) { collision.gameObject.transform.SetParent(this.transform); } void OnCollisionExit2D(Collision2D collision) { collision.gameObject.transform.SetParent(null); } } //オブジェクトのコード using System.Collections; using System.Collections.Generic; using UnityEngine; public class ObjectController : MonoBehaviour { Rigidbody2D rigid; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { //-5未満でオブジェクト削除 if(transform.position.y<-5) { Destroy(gameObject); } } void OnCollisionEnter2D(Collision2D collision) { } void OnCollisionStay2D(Collision2D collision) { //オブジェクト同士を親子関係に if (collision.gameObject.tag == "Object"|| collision.gameObject.tag == "Object2" || collision.gameObject.tag == "Object3" ) { collision.gameObject.transform.SetParent(this.transform); } } void OnCollisionExit2D(Collision2D collision) { //離れたら親子関係削除 if (collision.gameObject.tag == "Object" || collision.gameObject.tag == "Object2" || collision.gameObject.tag == "Object3" ) { collision.gameObject.transform.SetParent(null); } } } //ランダムで落下させる using System.Collections; using System.Collections.Generic; using UnityEngine; public class ObjectGenerator : MonoBehaviour { public GameObject[] bases; //prefab public Camera mainCamera; //カメラ取得用変数 float time = 0; //次のオブジェクト落とすまでの時間 float dropSpeed = -0.1f; //落下速度 float pivotHeight = 8; //落下位置 int number = 0; //ランダムな値を入れる // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { time -= Time.deltaTime; if (time <= 0.0f) { time = 5.0f; //時間入れ直し number = Random.Range(0, bases.Length); //どのオブジェクトを落とすかランダムに決める int x = Random.Range(-7, 7); //落下位置のX座標をランダムに Instantiate(bases[number], new Vector3(0, pivotHeight, 0), Quaternion.identity); //オブジェクト、落下位置、角度 pivotHeight += 0.2f; //オブジェクトを生成したら落下位置を上にあげる transform.Translate(0, this.dropSpeed, 0); //オブジェクト落下 } } } //参考にさせていただいた追加のスクリプト using System.Collections; using System.Collections.Generic; using UnityEngine; public class ObjectFixed : MonoBehaviour { public GameObject floor; // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { } void OnCollisionEnter2D(Collision2D collision) { collision.transform.parent = floor.transform; } void OnCollisionExit2D(Collision2D collision) { collision.transform.parent = null; } }
436

2020/09/17 10:07 編集

>追加のスクリプトは私が質問で載せたオブジェクトのコードと両方を落下物となるものにドラッグアンドドロップするということで合っていますでしょうか? 検証した際、質問に記載されていたコードは使ってません。 最初のコメントのコードに追加して試しました。 エラー内容は落下物のインスペクターに、床が割り当てられていないからだと思われます(ObjectFixedのfloorが空)。 インスペクターから、floorに床を割り当ててください(必要がありましたらプレファブ化も)。 書くのを端折ってしまい申し訳ないです。
riririri_

2020/09/17 11:27

こちらこそ何度も申し訳ございません。本当に助かっています。 床をprefab化をしないと割り当てができないようだったので、prefab化してからやってみたのですが、Setting the parent of a transform which resides in a Prefab Asset is disabled to prevent data corruption というエラーが出てきました。また、prefab化した他の落下物たちが衝突した際にも同じようなエラーが出てきてしまいます。 コードは436様に送っていただいた2のものを使用し、対処法を調べてみてpublic GameObject floor;をpublic GameObject floor = Instantiate(Player) as GameObject;にしてみたのですが、(prefabの名前がPlayerなのでPlayerと入っています)現在のコンテキストに'Player'という名前は存在しません。となってしまいます。対処法が間違っているのでしょうか...?
436

2020/09/17 12:41

prefab化しなくてもできる気がするのですが、私の知らない何かが何かしらの影響をしているのかもしれません。。。 public GameObject floor; // Start is called before the first frame update void Start() { floor = GameObject.Find("Player"); } で動けば幸いです。
riririri_

2020/09/17 12:57

無事に動きました!本当にありがとうございました! 積み上げてたものが落ちてきたものを弾くと親子関係が解除されてしまうのですが...これは仕方ないのでしょうか...? でも本当に助かりました...!
riririri_

2020/09/17 13:06

申し訳ありません、OnCollisionEnter2DをOnCollisionStay2Dに変えたらできました!改めて本当にありがとうございました!そして何日も付き合わせてしまい誠に申し訳ございませんでした...
436

2020/09/17 13:14

解決したみたいでよかったです。 頑張ってください!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問