前提・実現したいこと
自由にカメラが回転し、対象となるオブジェクトを任意の角度で確認できるようにしたい。
発生している問題・エラーメッセージ
ある対象の物体を中心に、カメラを球面座標で動かしたいのですが、Targetとなるオブジェクトにより挙動が異なってしまい困っています。
上手くいく例としてはUnity上で作成したCubeやPlaneをTargetとすると、Positionに関係なくオブジェクト中心にカメラは回転してくれます。
いかない例としては、WBboneという自分で作成した.objの拡張子のオブジェクトを対象にすると、対象物体よりも随分と上を回転してしまいます。
カメラの動きのスクリプトは球面座標によるカメラの操作のTPSを参考にし、"float distance = 1f"に変更しただけとなります。
このスクリプトを画像のようにObservationCameraObjectという空のオブジェクトに入れています。
Cameraとの親子関係も画像の通りとなります。
CameraFixObject,CameraともにPotion、Rotationの設定は0です。
ObservaionCameraObjectのTargetに対象としたいオブジェクトを入れています。
このTargetのオブジェクトによって挙動が思い通りにいかず困っています。
WBbone、RFemともに元はCTのDICOMデータであり、3D Slicerというソフトを使用して作成しています。
Sceneに配置した際、サイズがとても大きく、Scaleを0.01にしてこのサイズ感です。
(赤いCubeのスケールが1なので元がいかに大きいことか…)
このサイズが大きいことが悪影響を及ぼしているのでしょうか。
Unity超初心者になります。教えて頂けますと大変助かります。
ーーー加筆ーーー
アドバイスを頂いたスクリプトを元のスクリプトに以下のように書き加えました。
public Transform target;
public float spinSpeed = 0.3f;
float distance = 15f;
Vector3 nowPos;
public Vector2 mouse = Vector2.zero;
Vector3 offset = new Vector3(0.0f, 10f, 0.0f);
void Start()
{
// 初期位置の取得
nowPos = transform.position;
}
void Update()
{
// マウスの移動の取得
if (Input.GetMouseButton(0))
{
mouse += new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * Time.deltaTime * spinSpeed;
}
mouse.y = Mathf.Clamp(mouse.y, -0.3f + 0.5f, 0.3f + 0.5f);
Vector3 lookAtPos = target.transform.position + offset;
Vector3 targetPos = new Vector3(
lookAtPos.x = distance * Mathf.Sin(mouse.y * Mathf.PI) * Mathf.Cos(mouse.x * Mathf.PI),
lookAtPos.y = distance * Mathf.Cos(mouse.y * Mathf.PI),
lookAtPos.z = distance * Mathf.Sin(mouse.y * Mathf.PI) * Mathf.Sin(mouse.x * Mathf.PI));
transform.position = targetPos;
transform.LookAt(lookAtPos);
}
}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
kabanさんのご回答でうまくいくようでしたら問題ありませんが、もう一つの可能性として、それら骨オブジェクトのモデル座標原点がとんでもない位置になっているということはないでしょうか?
ご参考にされたTPS用カメラコントローラーのコードでは、注目対象のpositionを中心に据えるようになっているようです。3D Slicerの動作がどうなっているか確認したわけではないのですが、もし変な位置が原点になってしまっていると、そこを中心にカメラが回転することになるでしょう。
代わりに、注目オブジェクトの持つRendererのbounds...つまりポリゴンメッシュを囲む直方体を調べて、その中心を注目点としてみるのはどうでしょうか。
using UnityEngine;
using System.Collections;
public class CameraContollerScript : MonoBehaviour
{
public Transform target;
public float spinSpeed = 1f;
float distance = 1f;
Vector3 nowPos;
Vector3 pos = Vector3.zero;
public Vector2 mouse = Vector2.zero;
Transform currentTarget; // 追加...現在注目しているオブジェクト
Vector3 currentTargetCenter; // 追加...注目中のオブジェクトの中心
void Start()
{
// 初期位置の取得
nowPos = transform.position;
}
void Update()
{
// マウスの移動の取得
if (Input.GetMouseButton(0))
{
mouse += new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y")) * Time.deltaTime * spinSpeed;
}
mouse.y = Mathf.Clamp(mouse.y, -0.3f + 0.5f, 0.3f + 0.5f);
// 球面座標系変換
pos.x = distance * Mathf.Sin(mouse.y * Mathf.PI) * Mathf.Cos(mouse.x * Mathf.PI);
pos.y = -distance * Mathf.Cos(mouse.y * Mathf.PI);
pos.z = -distance * Mathf.Sin(mouse.y * Mathf.PI) * Mathf.Sin(mouse.x * Mathf.PI);
pos *= nowPos.z;
pos.y += nowPos.y;
UpdateCurrentTargetCenter(); // 追加...中心点を適宜再計算
// 座標の更新
transform.position = pos + currentTargetCenter; // 変更...target.positionの代わりにcurrentTargetCenterを見る
transform.LookAt(currentTargetCenter); // 変更...target.positionの代わりにcurrentTargetCenterを見る
}
// 追加...もしターゲットが変わった場合、中心点を再計算するメソッド
void UpdateCurrentTargetCenter()
{
if (target != currentTarget)
{
currentTarget = target;
if (currentTarget == null)
{
currentTargetCenter = Vector3.zero; // ターゲットがnullなら(0, 0, 0)を中心とする
}
else
{
Renderer[] renderers = currentTarget.GetComponentsInChildren<Renderer>(); // 注目オブジェクトおよびその子の持つすべてのレンダラーを探す
int rendererCount = renderers.Length; // 見つかったレンダラーの数
if (rendererCount > 0)
{
Bounds unitedBounds = renderers[0].bounds; // 0番目レンダラーのバウンディングボックスを取得
for (int i = 1; i < rendererCount; i++)
{
unitedBounds.Encapsulate(renderers[i].bounds); // unitedBoundsに1番目以降のレンダラーのバウンディングボックスを結合していく
}
currentTargetCenter = unitedBounds.center; // 結合したバウンディングボックスの中心を新たな中心点とする
}
else
{
currentTargetCenter = currentTarget.position; // レンダラーがないオブジェクトの場合、positionを中心とする
}
}
}
}
}
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
checkベストアンサー
0
スクリプトに問題があるかもしれません。
もしカメラの位置を調節したい場合、次のようにスクリプトを書き換えるといいと思います。
Vector3 offset = new Vector3 (0.0f, 4.3f, 0.0f);
Vector3 lookAtPos = target.transform.position + offset;
Vector3 targetPos = new Vector3 (
lookAtPos.x + distance * Mathf.Sin (mouse.y * Mathf.PI) * Mathf.Cos (mouse.x * Mathf.PI),
lookAtPos.y + distance * Mathf.Cos (mouse.y * Mathf.PI),
lookAtPos.z + distance * Mathf.Sin (mouse.y * Mathf.PI) * Mathf.Sin (mouse.x * Mathf.PI));
transform.position = targetPos;
transform.LookAt (lookAtPos);
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.23%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2018/03/22 08:45
最初はカメラが悪いものだと思っていたのですが、昨夜、座標原点がとんでもない位置にあり、そこを中心に回転していることに気づきましたが、なかなか思うような答えがなく、苦戦していました。
まさに今欲しい回答をして頂きました。ありがとうございます!!
注目オブジェクトのpositionを中心に捉えていたことが原因だったんですね。。
Bongo様のスクリプトで思い描いていた通りのカメラの動きになりました。
本当にありがとうございました。ここ3日悩んでいたことがやっと解決しました。
2018/03/22 08:48
初心者としては理解しやすく、とても助かりました。