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

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

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

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

2回答

651閲覧

ドラッグでキャラクターをエリアの端に移動する際に画面外へ移動しないようにしたい

Wings-12

総合スコア18

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2019/03/24 22:06

編集2019/03/25 10:46

お世話になります。

現在下記リンクの動画にあるように、
Androidのスマホ上でキャラクターをドラッグして移動し、
タップしたら、タップした位置に移動するように処理を作っています。

参考にした動画

今実現したい処理(希望する動き)は、上記の移動処理を以下の①、②ように実装することです。

①下記画像の明るい黄色で囲っている青いエリア内でドラッグしたときに、キャラクターがドラッグした動きに追従して移動すること。

②下記画像の明るい黄色で囲っている青いエリア内でタップしたときに、タップした位置まで、キャラクターがタップする前の位置からずっと描画されながら(ワープするのではなく)直線的に移動すること。

問題は、上記のキャラクター移動の際に、下記画像のような、
青いエリアの右端へキャラクターが移動した際に、
キャラクターがずっと上に行くか下に行くかしてしまうことがあることです。

下記画像:
イメージ説明

作成したソースコード:

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using Common; 5using System; 6/// <summary> 7/// Player1を操作するクラス 8/// 主に移動処理を書いている。 9/// </summary> 10public class Player1Controller : MonoBehaviour 11{ 12 // Player1のバトル開始座標 13 Vector3 player1_startPosition = new Vector3(-410.0f, -92.0f, 0.0f); 14 // タッチパネルをタップした位置を取得 15 Touch touch; 16 Vector3 touchPosition; 17 // Player1を1マス分前へ表示 18 Vector3 oneSquareForward = new Vector3(60.0f, 0.0f); 19 // ワールド座標でthis.transform.positionプロパティをアップデートする変数 20 Vector3 player1Position; 21 // Rigidbody2Dを使ったドラッグ移動処理 22 Rigidbody2D rigidbody2D; 23 Vector3 moveDirection; 24 float moveSpeed = 20.0f; 25 26 // Use this for initialization 27 void Start() 28 { 29 // このtransform自身のlocalPositionを初期化 30 this.transform.localPosition = player1_startPosition; 31 player1Position = this.transform.position; 32 33 //Rigidbody2Dのコンポート取得 34 rigidbody2D = GetComponent<Rigidbody2D>(); 35 } 36 // Update is called once per frame 37 void Update() 38 { 39 if (Input.touchCount > 0) 40 { 41 // タッチパネルをタップした位置を取得 42 touch = Input.GetTouch(0); 43 touchPosition = Camera.main.ScreenToWorldPoint(touch.position); 44 touchPosition.z = 0.0f; 45 46 // 以下青エリア内から赤エリアへフリック入力すると 47 //Player1が画面外へ飛んで行く不具合あり 48 49 // 青エリア内の移動処理 50 if (touchPosition.y < BattleArea.myUpperSide && 51 BattleArea.myLowerSide < touchPosition.y && 52 touchPosition.x + oneSquareForward.x < BattleArea.myRightSide && 53 BattleArea.myLeftSide < touchPosition.x + oneSquareForward.x) 54 { 55 // ドラッグ移動処理 56 moveDirection = touchPosition + oneSquareForward - this.transform.position; 57 rigidbody2D.velocity = new Vector2(moveDirection.x, moveDirection.y) * moveSpeed; 58 if (touch.phase == TouchPhase.Ended) 59 { 60 rigidbody2D.velocity = Vector2.zero; 61 } 62 } 63 // 青エリア外右側の処理 64 else if (BattleArea.myRightSide - oneSquareForward.x <= touchPosition.x && 65 // 敵エリアをタップしたら移動しないように自エリア最前列まで移動可能 66 touchPosition.x < BattleArea.myRightSide) 67 { 68 moveDirection = touchPosition + oneSquareForward - this.transform.position; 69 if (touch.phase == TouchPhase.Ended) 70 { 71 rigidbody2D.velocity = Vector2.zero; 72 } 73 else if (touch.phase == TouchPhase.Stationary) 74 { 75 rigidbody2D.velocity = Vector2.zero; 76 } 77 else if (touch.phase == TouchPhase.Moved) 78 { 79 rigidbody2D.velocity = new Vector2(0.0f, moveDirection.y) * moveSpeed; 80 if (this.transform.position.y <= BattleArea.myLowerSide) 81 { 82 player1Position.x = BattleArea.myRightSide; 83 player1Position.y = BattleArea.myLowerSide; 84 this.transform.position = player1Position; 85 } 86 else if (BattleArea.myUpperSide <= this.transform.position.y) 87 { 88 player1Position.x = BattleArea.myRightSide; 89 player1Position.y = BattleArea.myUpperSide; 90 this.transform.position = player1Position; 91 } 92 } 93 else 94 { 95 rigidbody2D.velocity = new Vector2(0.0f, moveDirection.y) * moveSpeed; 96 } 97 Debug.Log("touch.phaseの中身は:" + touch.phase); 98 Debug.Log("rigidbody2D.velocityの値は:" + rigidbody2D.velocity); 99 } 100 } 101 } 102}
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Common { public static class BattleArea { // 1マス分の移動量 public const float oneSquareUpDown = 162.0f; public const float oneSquareRightLeft = 165.0f; // 自エリアにおける各辺の座標 public const float myUpperSide = 210.0f; public const float myLowerSide = -33.0f; public const float myLeftSide = 98.0f; public const float myRightSide = 289.0f; } }

解決のために試したことは、
まず、青いエリアから赤いエリアへフリック入力するようにキャラクターを移動させると、上記のソースコードの中の条件文(下記のソースコードの箇所)
の中に入るので、その際のtouch.phaseの値と、rigidbody2D.velocityの値を確認しました。

// 青エリア外右側の処理 else if (BattleArea.myRightSide - oneSquareForward.x <= touchPosition.x && // 敵エリアをタップしたら移動しないように自エリア最前列まで移動可能 touchPosition.x < BattleArea.myRightSide)

確認したtouch.phaseの値と、rigidbody2D.velocityの値:
イメージ説明

確認結果から、touch.phaseがMovedのときにrigidbody2D.velocityが処理され、
青いエリアの外へキャラクターが移動してしまうことが分かったので、
Movedのときの処理を修正しようと思いました。

しかしどう修正したら、実現したい処理を作れるのか分かりませんでした。

Movedのときに、rigidbody2D.velocity = Vector2.zeroしたら、
今度は青いエリアの右端でキャラクターが動かなくなってしまうし、

そうであれば、Movedのときはthis.transform.positionの座標をプロパティを使って更新しようとしたら、
rigidbody2D.velocityが処理され続けてしまうのか、キャラクターが青エリア外へ移動してしまうし...

どうか解決のためのアドバイスをお願いします。

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

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

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

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

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

sakura_hana

2019/03/25 02:42

そもそも(強制的に静止させる目的以外で)velocityに対し直接値を代入してしまうのはあまりよくない(物理演算が狂うかもしれないから)というのはさておき。 「青いエリアの右端でキャラクターが動かなくなってしまう」のは意図に反するような書き方をしていますが、希望する動きはどんなものでしょうか?
Wings-12

2019/03/25 10:49

アドバイスとご指摘をありがとうございます。 質問内容を修正し、希望する動きを加筆ました。 まだわかりくいところがありましたら、大変申し訳ありませんが、もしよろしければご指摘をお願いします。
guest

回答2

0

えー、Maths.Clampという関数で移動範囲の制限をできます。
それを使ってはどうでしょうか?
Math.Clamp();の例をあげておきます。
キャラクター(gameobject)=player
画面の右端、左端をそれぞれ(float) = xr,xl
画面の上端、下端をそれぞれ(float) = yu,yd
として書いていきます。

C#

1Vector3 pPos = player.transform.position; 2pPos.x = Mathf.Clamp(xr,xl); 3pPos.y = Maths.Clamp(yu,yd); 4played.transform.position = pPos;

こんな感じで行けるはずです。
頑張ってください!!

投稿2020/08/07 11:48

kamo-tan-31

総合スコア12

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

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

Wings-12

2020/08/10 23:16

時間たっているのに回答をありがとうございます。 参考にさせて頂き、修正します。
guest

0

単純に座標について勘違いしている気がします。

rigidbody2D.velocity = Vector2.zero

この様なやり方では、壁にめり込んでしまった時、ずっと通るのは明白です。
下記の様にしてみてはいかがでしょうか?

Vector2 move = new Vector2(3,5);//この値はてきとう rigidbody2D.velocity += move; if(壁との衝突判定()){ rigidbody2D.velocity -= move; }

投稿2019/03/25 04:56

stdio

総合スコア3307

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

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

Wings-12

2019/03/25 22:04

アドバイスありがとうございます。 ただ質問内容が悪く申し訳ありません。 壁にめり込んだ時、キャラクターが移動しなくなる処理を作りたいのではなく、 壁にめり込んだ時、左手指の位置から、左手指と被ってキャラクターが見えなくならないくらい右側に行った位置にキャラクターが常に描画するように処理を作りたいです。 私は上手く人に物事を伝えるのが苦手なので、分かりにくくてすみません... 上記でも分かりにくければ、画像やgifで説明させていただきたいです。
stdio

2019/03/26 01:04

「左手指の位置から、左手指と被ってキャラクターが見えなくならないくらい右側に行った位置にキャラクターが常に描画するように処理」とは、青エリアから出た場合青エリアから少し顔を出す様な位置で停止させたいという事でしょうか? それなら、rigidbody2Dのwidthとheightを取得した分、青エリアを広げればいいんですよ。 疑似的なプログラムで申し訳ありませんがこんな感じの考え方でいいのではないでしょうか? Vector2 wallLT = new Vector2(100 - width,100 - height);//左上の壁、値はてきとう Vector2 wallRB = new Vector2(1180 + width,620 + height);//右下の壁、値はてきとう
Wings-12

2019/03/26 22:00

大変申し訳ありません... 「左手指の位置から、左手指と被ってキャラクターが見えなくならないくらい右側に行った位置にキャラクターが常に描画するように処理」とは、青エリアから出た場合青エリアから少し顔を出す様な位置で停止させたいという事でしょうか? → 停止したい処理は一部それで合ってますが、伝えきれてない部分があります... 本当にすみません...週末までに質問内容の実現したい処理を修正するか、自力で解決します....
stdio

2019/03/27 01:30

そうですか、頑張ってください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問