回答編集履歴

2

視点操作についての検討結果を追記

2019/07/11 20:34

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -97,4 +97,83 @@
97
97
  }
98
98
  ```
99
99
 
100
- 動かしてみた感想としては、操作感度調整目的でパラメーターを書き換えるなら`m_MaxSpeed`だけでもいいかもしれませんね。カメラが操作しにくくなる...みたいな特殊な演出をするのでしたらいいでしょうが、もし精密エイミングモード的な位置づけでカメラを遅くするのでしたら、加速時間・減速時間を長くしすぎるともっさり感が強すぎるかもしれません。
100
+ 動かしてみた感想としては、操作感度調整目的でパラメーターを書き換えるなら`m_MaxSpeed`だけでもいいかもしれませんね。カメラが操作しにくくなる...みたいな特殊な演出をするのでしたらいいでしょうが、もし精密エイミングモード的な位置づけでカメラを遅くするのでしたら、加速時間・減速時間を長くしすぎるともっさり感が強すぎるかもしれません。
101
+
102
+ #追記
103
+ まず、プレイヤーによる視点操作を無効化する件については単にX軸・Y軸の入力ソース名...[m_InputAxisName](https://docs.unity3d.com/Packages/com.unity.cinemachine@2.1/api/Cinemachine.AxisState.html#Cinemachine_AxisState_m_InputAxisName)を空欄に変えるだけでよさそうでした。
104
+
105
+ ※ご注意いただきたいのですが、デフォルトでは「Save During Play」がオンになっています。何らかのパラメーター...たとえば今回の入力ソース名の場合、それらを空欄に書き換えたままプレイモードを終了させると、変更が元に戻らず保存されていますので次回プレイモードにしたときに最初からカメラが動かせなくなってしまうでしょう。
106
+ プレイモード終了タイミングでパラメーターを復元するようなコードにしてもいいと思いますが、正しく復元するにはスクリプト実行順の調整も必要そうだったりで少々面倒そうに感じました。ですのでプレイモード中にパラメーター調整を行いたい場合以外は、素直に「Save During Play」をオフにした方がいいかと思います。
107
+
108
+ あとはスクリプトからの操作ですが、こっちはちょっとやっかいそうです。下記コードのコメント内でも言及しましたが、手動操作の時と同様のイメージで現在の向きから相対的に動かすのでしたら[m_InputAxisValue](https://docs.unity3d.com/Packages/com.unity.cinemachine@2.1/api/Cinemachine.AxisState.html#Cinemachine_AxisState_m_InputAxisValue)に入力量を入れてやればよさそうでした。さらに`m_MaxSpeed`書き換えも併用すれば回転速度を正確にコントロールできそうです。この動作で問題なければシンプルで済みますのでおすすめかと思います。
109
+
110
+ ```C#
111
+ using Cinemachine;
112
+ using UnityEngine;
113
+
114
+ [RequireComponent(typeof(CinemachineFreeLook))]
115
+ public class CameraLocker : MonoBehaviour
116
+ {
117
+ private CinemachineFreeLook freeLook;
118
+ private string xAxisName = string.Empty;
119
+ private string yAxisName = string.Empty;
120
+
121
+ private void Start()
122
+ {
123
+ this.freeLook = this.GetComponent<CinemachineFreeLook>();
124
+
125
+ // X軸、Y軸の設定を覚えておく
126
+ this.xAxisName = this.freeLook.m_XAxis.m_InputAxisName;
127
+ this.yAxisName = this.freeLook.m_YAxis.m_InputAxisName;
128
+ }
129
+
130
+ private void Update()
131
+ {
132
+ if (Input.GetKeyDown(KeyCode.Space))
133
+ {
134
+ // スペースバーが押し下げられたら入力元の名前をを空にする
135
+ this.freeLook.m_XAxis.m_InputAxisName = string.Empty;
136
+ this.freeLook.m_YAxis.m_InputAxisName = string.Empty;
137
+
138
+ // 入力値も消去して、ロック後に余力で回り続けてしまうのを防ぐ
139
+ this.freeLook.m_XAxis.m_InputAxisValue = 0.0f;
140
+ this.freeLook.m_YAxis.m_InputAxisValue = 0.0f;
141
+ }
142
+ else if (Input.GetKeyUp(KeyCode.Space))
143
+ {
144
+ // スペースバーが離されたら設定を復元する
145
+ this.freeLook.m_XAxis.m_InputAxisName = this.xAxisName;
146
+ this.freeLook.m_YAxis.m_InputAxisName = this.yAxisName;
147
+ }
148
+
149
+ if (Input.GetKey(KeyCode.Space))
150
+ {
151
+ // ロック中(スペースバーが押されている間)...
152
+
153
+ // プレイヤーの手動操作をシミュレートするイメージでm_InputAxisValueに
154
+ // 値を入れてやれば、現在の角度から相対的に回転すると思います
155
+ // たとえば下記のようにすると、垂直位置はゆっくり上リグへ移動していき
156
+ // 水平位置はゆっくり時計回りに回転するでしょう
157
+ // (ただし各軸の「Invert」を切り替えている場合は向きが逆になるはずです)
158
+ this.freeLook.m_XAxis.m_InputAxisValue = -0.1f;
159
+ this.freeLook.m_YAxis.m_InputAxisValue = 0.1f;
160
+
161
+ /*
162
+ // しかし相対値ではなく絶対値で向きを指定するのはやっかいそうです
163
+ // Y軸については意図通り操作できそうでしたが...
164
+ this.freeLook.m_YAxis.Value = 0.75f; // 上リグと中リグの中間位置
165
+
166
+ // X軸で同じことをやろうとしても、Binding ModeがSimple Follow With World Upだと
167
+ // くるくる回り続けて使い物にならないでしょう
168
+ this.freeLook.m_XAxis.Value = 90.0f; // 基準方向に対して90°の位置にしたつもり
169
+ */
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ やっかいなのは相対値ではなく絶対的に向きを指定したい場合で、Y軸については[m_YAxis.Value](https://docs.unity3d.com/Packages/com.unity.cinemachine@2.1/api/Cinemachine.AxisState.html#Cinemachine_AxisState_Value)に0~1の値(0で下、0.5で中央、1で上のリグ)を代入すればいいので楽そうでしたが、X軸はFreeLookCameraの「Orbits」→「[Binding Mode](https://docs.unity3d.com/Packages/com.unity.cinemachine@2.1/api/Cinemachine.CinemachineFreeLook.html#Cinemachine_CinemachineFreeLook_m_BindingMode)」の設定によって挙動が変化するようです。
176
+ 「World Space」とかでしたらY軸と同様に`m_XAxis.Value`に代入することで操作できますが、デフォルトの「Simple Follow With World Up」ではそうはいかないようでした。「World Space」だとキャラクターをカメラに対して横に走らせても角度が変わらないのに対し、「Simple Follow With World Up」はカメラの移動量が最小限になるためいい感じに移動方向へパンして自然なカメラワークになり魅力的ですが、スクリプトからのコントロールをするには面倒ですね。
177
+
178
+ バインディングモードもスクリプトから切り替えてやることで何とかできるのかもしれませんが、モード切り替わり時に視点が飛んでしまうのを防ぐにはカメラ位置調整が必要で、やはり一筋縄にはいかなそうです。
179
+ そこまでするぐらいならこの際もう1基バーチャルカメラを作成してキャラクターに追従させ、自由操作モードではFreeLookをアクティブに、強制視点モードでは追加のバーチャルカメラをアクティブにする...みたいなアプローチの方がCinemachineの流儀に合っていそうでいいんじゃないかと思うのですが、いかがでしょうかね?

1

フィールドへの直接アクセスを追記

2019/07/11 20:34

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -66,6 +66,33 @@
66
66
  this.freeLook.m_XAxis = xAxis;
67
67
  this.freeLook.m_YAxis = yAxis;
68
68
  }
69
+
70
+ // m_XAxis、m_YAxisはプロパティではなくフィールドなので、内部のメンバーに
71
+ // 直接アクセスしてもいいでしょう
72
+ // AxisStateのサイズは少し大きめ(88バイト)のようですので、頻繁に書き換えるなら
73
+ // 直接アクセス方式の方が効率的なような気がします
74
+ /*
75
+ if (Input.GetKeyDown(KeyCode.Space))
76
+ {
77
+ this.freeLook.m_XAxis.m_MaxSpeed = this.slowModeMaxSpeedX;
78
+ this.freeLook.m_XAxis.m_AccelTime = this.slowModeAccelTimeX;
79
+ this.freeLook.m_XAxis.m_DecelTime = this.slowModeDecelTimeX;
80
+
81
+ this.freeLook.m_YAxis.m_MaxSpeed = this.slowModeMaxSpeedY;
82
+ this.freeLook.m_YAxis.m_AccelTime = this.slowModeAccelTimeY;
83
+ this.freeLook.m_YAxis.m_DecelTime = this.slowModeDecelTimeY;
84
+ }
85
+ else if (Input.GetKeyUp(KeyCode.Space))
86
+ {
87
+ this.freeLook.m_XAxis.m_MaxSpeed = this.quickModeMaxSpeedX;
88
+ this.freeLook.m_XAxis.m_AccelTime = this.quickModeAccelTimeX;
89
+ this.freeLook.m_XAxis.m_DecelTime = this.quickModeDecelTimeX;
90
+
91
+ this.freeLook.m_YAxis.m_MaxSpeed = this.quickModeMaxSpeedY;
92
+ this.freeLook.m_YAxis.m_AccelTime = this.quickModeAccelTimeY;
93
+ this.freeLook.m_YAxis.m_DecelTime = this.quickModeDecelTimeY;
94
+ }
95
+ */
69
96
  }
70
97
  }
71
98
  ```