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

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

ただいまの
回答率

90.38%

  • Unity

    5837questions

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

  • Unity3D

    1923questions

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

CinemachineのVirtualCameraの感度をスクリプトから参照したい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 70

Harumaro

score 26

UnityでCinemachineというカメラAssetを使っています。
そのCinemachineFreeLookCameraというモードで、カメラ感度をスクリプトから参照したいのですが、調べてもわかりませんでした。カメラ感度を参照する方法をご教授いただきたいです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

マニュアルによれば、X軸、Y軸についてそれぞれ「Max Speed」、「Accel Time」、「Decel Time」のパラメーターがあり、「最大速度」、「目標速度まで達するのにかかる加速時間」、「入力がなくなったときに速度がゼロに戻るのにかかる減速時間」を意味するようです。

X軸パラメーターはm_XAxis、Y軸パラメーターはm_YAxisから一塊のAxisState構造体として取得および設定できるようでした。ここをいじってみてはいかがでしょうか?

using Cinemachine;
using UnityEngine;

[RequireComponent(typeof(CinemachineFreeLook))]
public class SensitivityController : MonoBehaviour
{
    [SerializeField] private float quickModeMaxSpeedX = 360.0f;
    [SerializeField] private float quickModeAccelTimeX = 0.1f;
    [SerializeField] private float quickModeDecelTimeX = 0.1f;
    [SerializeField] private float quickModeMaxSpeedY = 2.0f;
    [SerializeField] private float quickModeAccelTimeY = 0.2f;
    [SerializeField] private float quickModeDecelTimeY = 0.1f;

    [SerializeField] private float slowModeMaxSpeedX = 60.0f;
    [SerializeField] private float slowModeAccelTimeX = 0.5f;
    [SerializeField] private float slowModeDecelTimeX = 0.5f;
    [SerializeField] private float slowModeMaxSpeedY = 0.2f;
    [SerializeField] private float slowModeAccelTimeY = 1.0f;
    [SerializeField] private float slowModeDecelTimeY = 0.5f;

    private CinemachineFreeLook freeLook;

    private void Start()
    {
        this.freeLook = this.GetComponent<CinemachineFreeLook>();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // スペースバーを押し下げるともっさりモード
            var xAxis = this.freeLook.m_XAxis;
            var yAxis = this.freeLook.m_YAxis;

            xAxis.m_MaxSpeed = this.slowModeMaxSpeedX;
            xAxis.m_AccelTime = this.slowModeAccelTimeX;
            xAxis.m_DecelTime = this.slowModeDecelTimeX;

            yAxis.m_MaxSpeed = this.slowModeMaxSpeedY;
            yAxis.m_AccelTime = this.slowModeAccelTimeY;
            yAxis.m_DecelTime = this.slowModeDecelTimeY;

            this.freeLook.m_XAxis = xAxis;
            this.freeLook.m_YAxis = yAxis;
        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            // スペースバーを離すときびきびモード
            var xAxis = this.freeLook.m_XAxis;
            var yAxis = this.freeLook.m_YAxis;

            xAxis.m_MaxSpeed = this.quickModeMaxSpeedX;
            xAxis.m_AccelTime = this.quickModeAccelTimeX;
            xAxis.m_DecelTime = this.quickModeDecelTimeX;

            yAxis.m_MaxSpeed = this.quickModeMaxSpeedY;
            yAxis.m_AccelTime = this.quickModeAccelTimeY;
            yAxis.m_DecelTime = this.quickModeDecelTimeY;

            this.freeLook.m_XAxis = xAxis;
            this.freeLook.m_YAxis = yAxis;
        }

        // m_XAxis、m_YAxisはプロパティではなくフィールドなので、内部のメンバーに
        // 直接アクセスしてもいいでしょう
        // AxisStateのサイズは少し大きめ(88バイト)のようですので、頻繁に書き換えるなら
        // 直接アクセス方式の方が効率的なような気がします
        /*
        if (Input.GetKeyDown(KeyCode.Space))
        {
            this.freeLook.m_XAxis.m_MaxSpeed = this.slowModeMaxSpeedX;
            this.freeLook.m_XAxis.m_AccelTime = this.slowModeAccelTimeX;
            this.freeLook.m_XAxis.m_DecelTime = this.slowModeDecelTimeX;

            this.freeLook.m_YAxis.m_MaxSpeed = this.slowModeMaxSpeedY;
            this.freeLook.m_YAxis.m_AccelTime = this.slowModeAccelTimeY;
            this.freeLook.m_YAxis.m_DecelTime = this.slowModeDecelTimeY;
        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            this.freeLook.m_XAxis.m_MaxSpeed = this.quickModeMaxSpeedX;
            this.freeLook.m_XAxis.m_AccelTime = this.quickModeAccelTimeX;
            this.freeLook.m_XAxis.m_DecelTime = this.quickModeDecelTimeX;

            this.freeLook.m_YAxis.m_MaxSpeed = this.quickModeMaxSpeedY;
            this.freeLook.m_YAxis.m_AccelTime = this.quickModeAccelTimeY;
            this.freeLook.m_YAxis.m_DecelTime = this.quickModeDecelTimeY;
        }
        */
    }
}

動かしてみた感想としては、操作感度調整目的でパラメーターを書き換えるならm_MaxSpeedだけでもいいかもしれませんね。カメラが操作しにくくなる...みたいな特殊な演出をするのでしたらいいでしょうが、もし精密エイミングモード的な位置づけでカメラを遅くするのでしたら、加速時間・減速時間を長くしすぎるともっさり感が強すぎるかもしれません。

追記

まず、プレイヤーによる視点操作を無効化する件については単にX軸・Y軸の入力ソース名...m_InputAxisNameを空欄に変えるだけでよさそうでした。

※ご注意いただきたいのですが、デフォルトでは「Save During Play」がオンになっています。何らかのパラメーター...たとえば今回の入力ソース名の場合、それらを空欄に書き換えたままプレイモードを終了させると、変更が元に戻らず保存されていますので次回プレイモードにしたときに最初からカメラが動かせなくなってしまうでしょう。
プレイモード終了タイミングでパラメーターを復元するようなコードにしてもいいと思いますが、正しく復元するにはスクリプト実行順の調整も必要そうだったりで少々面倒そうに感じました。ですのでプレイモード中にパラメーター調整を行いたい場合以外は、素直に「Save During Play」をオフにした方がいいかと思います。

あとはスクリプトからの操作ですが、こっちはちょっとやっかいそうです。下記コードのコメント内でも言及しましたが、手動操作の時と同様のイメージで現在の向きから相対的に動かすのでしたらm_InputAxisValueに入力量を入れてやればよさそうでした。さらにm_MaxSpeed書き換えも併用すれば回転速度を正確にコントロールできそうです。この動作で問題なければシンプルで済みますのでおすすめかと思います。

using Cinemachine;
using UnityEngine;

[RequireComponent(typeof(CinemachineFreeLook))]
public class CameraLocker : MonoBehaviour
{
    private CinemachineFreeLook freeLook;
    private string xAxisName = string.Empty;
    private string yAxisName = string.Empty;

    private void Start()
    {
        this.freeLook = this.GetComponent<CinemachineFreeLook>();

        // X軸、Y軸の設定を覚えておく
        this.xAxisName = this.freeLook.m_XAxis.m_InputAxisName;
        this.yAxisName = this.freeLook.m_YAxis.m_InputAxisName;
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            // スペースバーが押し下げられたら入力元の名前をを空にする
            this.freeLook.m_XAxis.m_InputAxisName = string.Empty;
            this.freeLook.m_YAxis.m_InputAxisName = string.Empty;

            // 入力値も消去して、ロック後に余力で回り続けてしまうのを防ぐ
            this.freeLook.m_XAxis.m_InputAxisValue = 0.0f;
            this.freeLook.m_YAxis.m_InputAxisValue = 0.0f;
        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            // スペースバーが離されたら設定を復元する
            this.freeLook.m_XAxis.m_InputAxisName = this.xAxisName;
            this.freeLook.m_YAxis.m_InputAxisName = this.yAxisName;
        }

        if (Input.GetKey(KeyCode.Space))
        {
            // ロック中(スペースバーが押されている間)...

            // プレイヤーの手動操作をシミュレートするイメージでm_InputAxisValueに
            // 値を入れてやれば、現在の角度から相対的に回転すると思います
            // たとえば下記のようにすると、垂直位置はゆっくり上リグへ移動していき
            // 水平位置はゆっくり時計回りに回転するでしょう
            // (ただし各軸の「Invert」を切り替えている場合は向きが逆になるはずです)
            this.freeLook.m_XAxis.m_InputAxisValue = -0.1f;
            this.freeLook.m_YAxis.m_InputAxisValue = 0.1f;

            /*
            // しかし相対値ではなく絶対値で向きを指定するのはやっかいそうです
            // Y軸については意図通り操作できそうでしたが...
            this.freeLook.m_YAxis.Value = 0.75f; // 上リグと中リグの中間位置

            // X軸で同じことをやろうとしても、Binding ModeがSimple Follow With World Upだと
            // くるくる回り続けて使い物にならないでしょう
            this.freeLook.m_XAxis.Value = 90.0f; // 基準方向に対して90°の位置にしたつもり
            */
        }
    }
}

やっかいなのは相対値ではなく絶対的に向きを指定したい場合で、Y軸についてはm_YAxis.Valueに0~1の値(0で下、0.5で中央、1で上のリグ)を代入すればいいので楽そうでしたが、X軸はFreeLookCameraの「Orbits」→「Binding Mode」の設定によって挙動が変化するようです。
「World Space」とかでしたらY軸と同様にm_XAxis.Valueに代入することで操作できますが、デフォルトの「Simple Follow With World Up」ではそうはいかないようでした。「World Space」だとキャラクターをカメラに対して横に走らせても角度が変わらないのに対し、「Simple Follow With World Up」はカメラの移動量が最小限になるためいい感じに移動方向へパンして自然なカメラワークになり魅力的ですが、スクリプトからのコントロールをするには面倒ですね。

バインディングモードもスクリプトから切り替えてやることで何とかできるのかもしれませんが、モード切り替わり時に視点が飛んでしまうのを防ぐにはカメラ位置調整が必要で、やはり一筋縄にはいかなそうです。
そこまでするぐらいならこの際もう1基バーチャルカメラを作成してキャラクターに追従させ、自由操作モードではFreeLookをアクティブに、強制視点モードでは追加のバーチャルカメラをアクティブにする...みたいなアプローチの方がCinemachineの流儀に合っていそうでいいんじゃないかと思うのですが、いかがでしょうかね?

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/11 13:14

    説明不足ですいません。プレイヤーが操作することで視点を回すのを一時的に禁止し、スクリプトから強制的に回したいということです。視点操作は一時的に無効になります。

    キャンセル

  • 2019/07/12 05:35 編集

    検討してみましたが、ダイレクトな角度指定までは達成できずすみません。追記の最後で言及したような、バーチャルカメラをもう一つ増やして、それをスクリプトでコントロールした方が楽な気がしてきました。

    キャンセル

  • 2019/07/12 06:53

    ご検討ありがとうございました。バーチャルカメラをもう一つ増やす方が確かに楽ですね。カメラを事前にもう一つセットしておく形で今回は行きたいと思います。ありがとうございました!

    キャンセル

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

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

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

  • Unity

    5837questions

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

  • Unity3D

    1923questions

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