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

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

ただいまの
回答率

90.34%

  • C#

    8230questions

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

  • Unity

    4886questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1583questions

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

Unityで対象となるオブジェクトによってカメラの挙動が変わってしまう

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 606

kaz2zak

score 24

 前提・実現したいこと

自由にカメラが回転し、対象となるオブジェクトを任意の角度で確認できるようにしたい。

イメージ説明

 発生している問題・エラーメッセージ

ある対象の物体を中心に、カメラを球面座標で動かしたいのですが、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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

kabanさんのご回答でうまくいくようでしたら問題ありませんが、もう一つの可能性として、それら骨オブジェクトのモデル座標原点がとんでもない位置になっているということはないでしょうか?
ご参考にされたTPS用カメラコントローラーのコードでは、注目対象のpositionを中心に据えるようになっているようです。3D Slicerの動作がどうなっているか確認したわけではないのですが、もし変な位置が原点になってしまっていると、そこを中心にカメラが回転することになるでしょう。

代わりに、注目オブジェクトの持つRendererbounds...つまりポリゴンメッシュを囲む直方体を調べて、その中心を注目点としてみるのはどうでしょうか。

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を中心とする
                }
            }
        }
    }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/22 08:45

    ご回答ありがとうございます。
    最初はカメラが悪いものだと思っていたのですが、昨夜、座標原点がとんでもない位置にあり、そこを中心に回転していることに気づきましたが、なかなか思うような答えがなく、苦戦していました。
    まさに今欲しい回答をして頂きました。ありがとうございます!!

    注目オブジェクトのpositionを中心に捉えていたことが原因だったんですね。。
    Bongo様のスクリプトで思い描いていた通りのカメラの動きになりました。
    本当にありがとうございました。ここ3日悩んでいたことがやっと解決しました。

    キャンセル

  • 2018/03/22 08:48

    分かりやすいようにスクリプトにコメントを書いて頂き重ね重ね感謝申し上げます。
    初心者としては理解しやすく、とても助かりました。

    キャンセル

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);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/21 14:03

    回答頂きありがとうございます。
    アドバイス頂いたスクリプトを自分なりに書き換えてみたのですが、対象のオブジェクトの裏側に行くことができなくなりました。。
    上記の質問欄に書き換えたスクリプトを載せるので見ていただければ幸いです。

    ```

    キャンセル

  • 2018/03/21 14:41

    targetPosを定義する際、lookAtPosに別の値を代入してしまっていることが原因と思われます。

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • C#

    8230questions

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

  • Unity

    4886questions

    Unityは、ユニティテクノロジーが開発したゲームエンジンです。 主にモバイルやブラウザ向けのゲーム製作に利用されていましたが、3Dの重力付きゲームが簡単に作成できることから需要が増え、現在はマルチプラットフォームに対応しています。 言語はC言語/C++で書かれていますが、C#、JavaScript、Booで書かれたコードにも対応しています。

  • Unity3D

    1583questions

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