前に
【Unity】ドラッグで回転盤を回転させるスクリプト
を書きました。続きです。
作ったアプリは
デザイン協力:Studio tama,syu 音素材:魔王魂
しかしいくつか問題がありました。
1.指で中央部分を横切るようにスワイプすると回転がぎゅんっ!となる
2.かちっ、とちょうどよいところで止まって欲しい
3.ルーレット盤のように指を離しても慣性で少し動いて欲しい
まず3の慣性は、指を離した後に
[javascript]disc.rigidbody.AddTorque (Vector3.forward * (10 * rotatePower)); // 慣性で回り続ける[/javascript]
とやるとうまくいきました。が!この後、2を解決しようと摩擦をつける物理法則だとかみえないストッパーだとかいろいろ試し始めたのですが、物理演算を使おうというこの発想がそもそも間違いでした。
ここは最近のWEBサイトでよくあるスライドショーと同じで、24度回転するごとに現在の表示倍数を1,2,3とカウントし、指を離したらそのカウントした数に24度掛けたとこまで自動で回してやればいいんです。
もちろん左回りの場合は算出した度数から24度ひいたところに回してやります。
これでかちっと止まるように。
[javascript]
// 他のオブジェクトとのリンク:
public var dummyPointer : Transform; // 空のゲームオブジェクトだけでいい (見えないけどね)
public var disc : Transform; // メインの回転盤
public var currentCursor : int;
public var audioClip : AudioClip;
// Variables:
private var dummyOffset : float;
private var discOffset : float;
private var discSpilitNumber : int = 15;
private var rotatePower : float; // 0より大きいなら右回り
private var autoMove : boolean = false; // 半端な位置からの移動
// A Flag:
private var mouseIsUp : boolean = true;
// Raycast SetUp:
var hit : RaycastHit;
function Update () {
var rotation ;
// マウス押したか:
if (Input.GetMouseButton(0)){
// 判定のRaycast発射:
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
// 光線が特定の名前のオブジェクトにあたった:
if (Physics.Raycast (ray, hit) && (hit.transform.name == "disc")){
// 常にダミーはあたった箇所を向く:
dummyPointer.LookAt(hit.point, Vector3.forward);
// マウスを押したときの初期処理:
if(mouseIsUp){
// ダミーとメイン回転盤の角度を覚えておく
dummyOffset = dummyPointer.eulerAngles.z;
discOffset = disc.eulerAngles.z;
// 最初のクリックでなくなる:
mouseIsUp = false;
}else{
// 最初のクリックでない (押し続け)
// ダミーから回転盤の回転をセットすることができる:
var z :float = discOffset + (dummyPointer.eulerAngles.z – dummyOffset);
rotatePower = z – disc.eulerAngles.z;
disc.eulerAngles.z = z;
}
}
autoMove = false;
} else {
// クリックが終わったらからフラグも戻す:
mouseIsUp = true;
autoMove = true;
disc.rigidbody.AddTorque (Vector3.forward * (10 * rotatePower)); // 慣性で回り続ける
}
disc.transform.position = new Vector3(0, 0, 0);
// 特定のポイントで止める
if (autoMove){
if (rotatePower < 0){
rotation = Quaternion.Euler(0, 0, currentCursor * (360/15));
} else {
rotation = Quaternion.Euler(0, 0, (currentCursor * (360/15)) + (360/15) );
}
disc.rotation = Quaternion.Slerp(disc.rotation, rotation, 0.1);
}
var oldCurrentCursor = currentCursor;
currentCursor = disc.eulerAngles.z / (360/discSpilitNumber);
if (oldCurrentCursor != currentCursor){
audio.PlayOneShot(audioClip);
}
}
[/javascript]
1についても簡単な方法がありました。真ん中付近をタッチで反応しなくしてやればいいのです。
穴の開いたモデリングをしてそこにColliderをつけるのではMeshColliderとなってしまい計算負荷が高いので、かぶせるように別のColliderを入れました。
SphearColliderはもっとも計算が軽いうえに、ぴったりサイズに収まるのでおあつらえむきですね。