【Unity】ドラッグでオブジェクトを回転させる

2020/4/17一部修正


余りオブジェクトを回転させる事ってないんですが、
私だけヽ(´~`;)ウーン

球転がし迷路を見た時に
どうやってオブジェクトをドラッグで回転させるの?
と疑問が湧きました。

少し考えてみたのですが、
ドラッグ開始ポイントを取得して、マウスの移動量から角度を割り出して、
出た角度をオブジェクトに代入する。

こんな感じなのかな~ と思いました。

しかし、移動量から角度を割り出す計算は、
三平方、余弦、オイラー変換が必要になりますヽ(´~`;)ウーン

学生時代、勉強を放棄していた私には、???? のオンパレードでっす。
(°-°;)ヾ(-_- ;) シモシモ・・


そこで、Google先生に泣きつく事にしました。(T^T) センセイ


こんぶさんの
Unity : マウスで物体を回転させる
がヒットしました。
いつも有益な情報をありがとうございますm(_ _)m

早速流用させてもらいまっす。(^ё^) ♪♪

まず、androidのセッティングをすませて、背景まで設置したら、
こんぶさんの情報通りのオブジェクトを追加します。
Rotation①.jpg
こんぶさんはBoxにされていますが、私はターゲットとしておきます。

続いて、
Rotation②.jpg
ハンドルが必要になるので、
ターゲットの子にImageを追加してハンドルを作成します。
ハンドルはターゲットの右上に配置しておけばいいかと。

これでUIの準備は完了!
新規Scriptを立ち上げて、こんぶさんのコードをコピペします。

Scriptはハンドルにアタッチします。

ハンドルには、Eventtriggerを二つ用意します。
Rotation③.jpg
・PointerDown
ハンドルをクリックした時の初期位置を取得
メソッドは、SetPos()を割り当てます。
・Drag
ハンドルを掴んでいる間の動き
メソッドは、Rotate()を割り当てます。


これで動くそうなので、PLAYしてハンドルを握ります。
スゲ~ ぐりぐり回ります (@@;;;)

このスクリプトでは、PowerPointやWord・Excelの
画像回転を意識して、作られたそうです。


さて、ここからなのですが、スマホゲーム上では画面をスワイプして
オブジェクトを回転させます。

画面のどこからでもアクセスできるようにしたいので、
改造をしてみたいと思います。


まず、ハンドルが必要ないので削除します。

続いて、スクリプトの改造をしていきます。

ハンドルをクリックして呼び出していたメソッドを
マウスクリックで呼び出せるように変更します。



bool Drag;//ドラッグ中のフラグ

void SetPos()
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
pos = Camera.main.ScreenToWorldPoint(Input.mousePosition); // マウス位置をワールド座標で取得
rotation = this.transform.rotation; // ターゲットの現在の角度を取得
Drag = true;
}
}

マウスのクリックは、keyDownとkeyUpで読み取るので、
keyDown中を判定する為のフラグを追加しました。

ハンドルを削除した事で、rotationの取得ができなくなるので、
rotation = transform.parent.rotation;

rotation = this.transform.rotation;
に変更して、Scriptはターゲットにアタッチします。

続いて、動きの方も変更します。

void Rotate()
{
if (Input.GetKeyUp(KeyCode.Mouse0))
{
Drag = false;
return;
}

vecA = pos - (Vector2)this.transform.position; //ある地点からのベクトルを求めるときはこう書くんだった
vecB = Camera.main.ScreenToWorldPoint(Input.mousePosition) - this.transform.position; // 上に同じく
// Vector2にしているのはz座標が悪さをしないようにするためです

angle = Vector2.Angle(vecA, vecB); // vecAとvecBが成す角度を求める
AxB = Vector3.Cross(vecA, vecB); // vecAとvecBの外積を求める

// 外積の z 成分の正負で回転方向を決める
if (AxB.z > 0)
{
this.transform.localRotation = rotation * Quaternion.Euler(0, 0, angle); // 初期値との掛け算で相対的に回転させる
}
else
{
this.transform.localRotation = rotation * Quaternion.Euler(0, 0, -angle); // 初期値との掛け算で相対的に回転させる
}
}

まず、keyUpで判断して、キーが押されている間は、
動作の処理を継続するようにします。

こちらも回転対象の指定がハンドルから見て、の処理なので、
全て、thisに書き換えます。

これで、クリックからドラッグ終了まで処理が行われるので、
処理タイミングをUpdateから監視します。


void Update()
{
if (Drag)
{
Rotate();
}
else
{
SetPos();
}
}

Scriptができたので、Unity側を修正します。

Rotation④.jpg
大げさに言いましたがターゲットにScriptをアタッチするだけです。
(V)o¥o(V)ふぉふぉふぉ(V)o¥o(V)

これで画面上をドラッグして指を動かせば、
オブジェクトも回転するはずです。

ドラッグしてる状況が分からないので、
指のイメージを置いてます。
白→何もしてない状態
黒→ドラッグ中

スマホの画面上ならどこからドラッグしても
反応してくれるようになります。

最後に完成版のスクリプトを
参考にして頂けると幸いです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RotationScript : MonoBehaviour
{
Vector2 pos; // クリック時のマウス位置
Quaternion rotation; // クリックしたときのターゲットの角度

Vector2 vecA; // ターゲットの中心からposへのベクトル
Vector2 vecB; // ターゲットの中心から現マウス位置へのベクトル

float angle; // vecAとvecBが成す角度
Vector3 AxB; // vecAとvecBの外積

bool Drag; //ドラッグ中のフラグ


void Update()
{
// マウスのクリック状態からメソッドを選択
if (Drag)
{
Rotate();
}
else
{
SetPos();
}
}

//マウスをクリックした時の処理
void SetPos()
{
//クリック時のマウスの初期位置とターゲットの現角度を取得
if (Input.GetKeyDown(KeyCode.Mouse0))
{
pos = Camera.main.ScreenToWorldPoint(Input.mousePosition); // マウス位置をワールド座標で取得
rotation = this.transform.rotation; // ターゲットの現角度を取得
Drag = true; // クリックフラグをONにする
}
}

//ドラッグ中かを判断して処理を行う
void Rotate()
{
//ドラッグが解除されたらフラグをOFFにしてReturn
if (Input.GetKeyUp(KeyCode.Mouse0))
{
Drag = false;
return;
}

//マウス初期位置のベクトルを求める
vecA = pos - (Vector2)this.transform.position;

//現マウス位置のベクトルを求める
vecB = Camera.main.ScreenToWorldPoint(Input.mousePosition) - this.transform.position;

// Vector2にしているのはz座標が悪さをしないようにするため

//マウスの初期位置と現マウス位置から角度と外積を求める
angle = Vector2.Angle(vecA, vecB); //角度を計算
AxB = Vector3.Cross(vecA, vecB); //外積を計算

// 外積の z 成分の正負で回転方向を決める
if (AxB.z > 0)
{
this.transform.localRotation = rotation * Quaternion.Euler(0, 0, angle); // 初期値との掛け算で相対的に回転させる
}
else
{
this.transform.localRotation = rotation * Quaternion.Euler(0, 0, -angle); // 初期値との掛け算で相対的に回転させる
}
}
}



読まれる事も無いと思いますが、
こんぶさんスクリプトを改造して申し訳ないです。m(_ _)m ゴメンナサイ

この記事へのコメント