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

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

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

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

解決済

1回答

2041閲覧

オブジェクトのドラッグ&ドロップで壁を通り抜けないようにしたい

tride

総合スコア68

C#

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

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

1クリップ

投稿2021/07/11 05:42

編集2021/07/11 13:47

表題の通りではありますが、オブジェクト(白立方体)をドラッグ&ドロップした時に、壁(青立方体)を通り抜けしないようにしたいです。
現在のコードでは、カーソル操作と違い、マウスポジションにオブジェクトが瞬間移動するので、通り抜けしてしまう原因自体は理解しているのですが、ここから改善策が思い浮かばずに行き詰っています。

なので、なにか別のやり方やアルゴリズム、もしくはアセットなど、表題の目的を解決できる方法を教えていただきたいです。


目的
・オブジェクト(白立方体)をドラッグ&ドロップした時に、壁(青立方体)を通り抜けしないようにしたい
・最終的には、この壁(青立方体)で四方を囲ったり、通路を作りたい。

困ってる事
・オブジェクト(白立方体)をドラッグ&ドロップした時に、壁(青立方体)を通り抜ける(埋まる)。

気になってる事
・通り抜けする時に抵抗感が若干あるので、この反発力?を増やせば実現できる?(但しそれが何のパラメータなのかは不明)
・下記ソースコードによるマウスによるドラッグ&ドロップでは、現在位置に瞬間移動しているので、このやり方がそもそもダメなのでは?
・壁(青立方体)にスクリプトを適用し、オブジェクト(白立方体)のMathf.Clampを反転してやればできるかもしれないが、範囲の反転方法が分からない。

実施した事
・類似の質問で、「使うとしたらrigidbody.velocity~」とあったので、試しに"壁に触れたらrigidbody.velocityを0にする"としたが、その後に移動できなくなる。
→なんらかのアルゴリズムで実現できそうだけど、アルゴリズムの案が浮かばない。
・Collision Detection」の項目を「Continuous」に設定
→マウスによる移動が指定座標への瞬間移動なので意味がないと理解。

その他
・床(濃紺)の移動範囲の制限はMathf.Clampで実現できた。
・カーソル操作の場合は意図通り、通り抜けできない事は別ソースで確認できた。

画面
画面

環境
・Unity 2021.1.12f1
・Visual Studio 2019

類似質問:https://teratail.com/questions/139884
参考サイト:https://www.ame-name.com/archives/4631

C#

1 2 /// <summary> 3 /// 3D空間上で位置判定を行う為の不可視の3Dステージ 4 /// </summary> 5 Plane Plane; 6 7 /// <summary> 8 /// 現在オブジェクトを掴んでいるかを判定するフラグ 9 /// </summary> 10 private bool isGrabbing; 11 12 /// <summary> 13 /// プレイヤーオブジェクト(位置変更用) 14 /// </summary> 15 /// <remarks>transformでは位置書き換えはできないので用意</remarks> 16 private Transform PlayerObject; 17 18 /// <summary> 19 /// 移動範囲となる床 20 /// </summary> 21 private GameObject WorldPlane; 22 23 // Start is called before the first frame update 24 void Start() 25 { 26 //原点よりY軸1メートル上にPlaneを作成(配置済みのプレーンより上の位置に配置) 27 Plane = new Plane(Vector3.up, Vector3.up); 28 29 WorldPlane = GameObject.Find("WorldPlane"); 30 } 31 32 // Update is called once per frame 33 void Update() 34 { 35 //左クリックされたか 36 if (Input.GetMouseButtonDown(0)) 37 { 38 // カーソルからカメラ奥方向へのレイ(不可視の点光線)を定義 39 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 40 41 // レイを発射 42 if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity)) 43 { 44 // タグで見分ける 45 if (hit.collider.tag == "Player") 46 { 47 //マウスドラッグ状態とする 48 isGrabbing = true; 49 50 // 掴んでいるtransformオブジェクトを保存 51 PlayerObject = hit.transform; 52 53 } 54 } 55 } 56 57 if (isGrabbing) 58 { 59 // カーソルからカメラ奥方向へのレイ(不可視の点光線)を定義 60 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 61 62 // Planeにレイを貫通させる 63 Plane.Raycast(ray, out float rayDistance); 64 65 // レイが当たった交点位置をプレイヤーオブジェクトの位置にする 66 PlayerObject.position = ray.GetPoint(rayDistance); 67 68 //左クリックボタンが離れた 69 if (Input.GetMouseButtonUp(0)) 70 { 71 isGrabbing = false; 72 } 73 } 74 75 //床の範囲を取得 76 float areaX = WorldPlane.GetComponent<Renderer>().bounds.size.x; 77 float areaZ = WorldPlane.GetComponent<Renderer>().bounds.size.z; 78 79 //プレイヤーの移動範囲を床面だけに制限 80 transform.position = new Vector3( 81 Mathf.Clamp(transform.position.x, -(areaX / 2), areaX / 2 ), 82 Mathf.Clamp(transform.position.y, 1, 1), 83 Mathf.Clamp(transform.position.z, -(areaZ / 2), areaZ / 2) 84 ); 85 86 87 }

追記_2021/07/11_22:43

Bongoさんのコードを実装してみた結果です。
白立方体のRigitbody>抗力を45にしたところ、マウスの早い動きでも貫通しなくなって想定した動きにかなり近いものになりました。
(抗力が低いと反対方向に跳ねすぎて飛んでいった)
しかし、以下Gifを見てもらうと分かるかと思いますが、ビョンビョンビョンとかなり高速にバウンドしてしまいます。
できればもう少し跳ねないのが理想ですが、悩ましい所。
実装

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

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

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

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

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

guest

回答1

0

ベストアンサー

確かにvelocity操作なら周りの物体と物理的に相互作用できそうですね。
試しに下記のように変更してみましたが、いかがでしょうか?

lang

1using UnityEngine; 2 3public class Player : MonoBehaviour 4{ 5 /// <summary> 6 /// 現在オブジェクトを掴んでいるかを判定するフラグ 7 /// </summary> 8 private bool isGrabbing; 9 10 /// <summary> 11 /// 3D空間上で位置判定を行う為の不可視の3Dステージ 12 /// </summary> 13 private Plane Plane; 14 15 /// <summary> 16 /// プレイヤーオブジェクト(位置変更用) 17 /// </summary> 18 /// <remarks>transformでは位置書き換えはできないので用意</remarks> 19 private Rigidbody PlayerObject; // PlayerObjectの型をRigidbodyに変更 20 21 /// <summary> 22 /// 移動範囲となる床 23 /// </summary> 24 private GameObject WorldPlane; 25 26 // Start is called before the first frame update 27 void Start() 28 { 29 //原点よりY軸1メートル上にPlaneを作成(配置済みのプレーンより上の位置に配置) 30 Plane = new Plane(Vector3.up, Vector3.up); 31 WorldPlane = GameObject.Find("WorldPlane"); 32 } 33 34 // Update is called once per frame 35 void Update() 36 { 37 //左クリックされたか 38 if (Input.GetMouseButtonDown(0)) 39 { 40 // カーソルからカメラ奥方向へのレイ(不可視の点光線)を定義 41 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 42 43 // レイを発射 44 if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity)) 45 { 46 // タグで見分ける 47 if (hit.collider.tag == "Player") 48 { 49 //マウスドラッグ状態とする 50 isGrabbing = true; 51 52 // 掴んでいるtransformオブジェクトを保存 53 PlayerObject = hit.rigidbody; // こちらもrigidbodyに変更 54 } 55 } 56 } 57 58 if (isGrabbing) 59 { 60 //左クリックボタンが離れた 61 if (Input.GetMouseButtonUp(0)) 62 { 63 isGrabbing = false; 64 } 65 } 66 67 //床の範囲を取得 68 float areaX = WorldPlane.GetComponent<Renderer>().bounds.size.x; 69 float areaZ = WorldPlane.GetComponent<Renderer>().bounds.size.z; 70 71 //プレイヤーの移動範囲を床面だけに制限 72 transform.position = new Vector3( 73 Mathf.Clamp(transform.position.x, -(areaX / 2), areaX / 2), 74 Mathf.Clamp(transform.position.y, 1, 1), 75 Mathf.Clamp(transform.position.z, -(areaZ / 2), areaZ / 2) 76 ); 77 } 78 79 // 移動をFixedUpdateのタイミングで行うように変更 80 void FixedUpdate() 81 { 82 if (isGrabbing) 83 { 84 // カーソルからカメラ奥方向へのレイ(不可視の点光線)を定義 85 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); 86 87 // Planeにレイを貫通させる 88 Plane.Raycast(ray, out float rayDistance); 89 90 // レイが当たった交点位置へ1フレームで移動するようにvelocityを設定する 91 PlayerObject.velocity = (ray.GetPoint(rayDistance) - PlayerObject.position) / Time.deltaTime; 92 } 93 } 94}

図

投稿2021/07/11 13:01

Bongo

総合スコア10811

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

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

tride

2021/07/11 13:49 編集

実施した内容を追記させて頂きました。
tride

2021/07/11 13:49

おっと、Gifに気付きませんでした。 BongoさんのGifの方はほぼ理想通りの動きだと思います。 Rigidbodyのパラーメータとか何か変更してますでしょうか?
tride

2021/07/11 14:03

失礼しました。 過去にマテリアルに反発設定を入れたのを忘れていました(汗 解除した結果、BongoさんのGif通りに動きました。 理想通りの動きで満足です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問