回答編集履歴

4

コメントの誤りを修正

2017/11/24 21:30

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -174,7 +174,7 @@
174
174
 
175
175
  var aD = aRIsNotZero ? aXZ / aR : Vector2.zero; // 真上から見たaの方角、aRがほぼ0ならVector2.zeroとして無回転にする
176
176
 
177
- var bXZ = new Vector2(b.x, b.z); // 真上から見たa
177
+ var bXZ = new Vector2(b.x, b.z); // 真上から見たb
178
178
 
179
179
  var bR = bXZ.magnitude; // bのY軸からの距離
180
180
 

3

カメラのスクリプト(LookRotation版)にSlerpの置き換え案を追加、旧カメラスクリプトを削除

2017/11/24 21:30

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
 
14
14
 
15
- カメラのスクリプト
15
+ カメラのスクリプト(LookRotation版)
16
16
 
17
17
  ```C#
18
18
 
@@ -24,52 +24,40 @@
24
24
 
25
25
  {
26
26
 
27
- private const float CameraDeltaOffsetSqrMagnitudeThreshold = 0.0001f; // 追加...offsetズレ判定のしきい値(回転終了判定方法を変更し、offsetが目標位置にほぼ一致したかで判定することにしました
27
+ private const float CameraDeltaOffsetSqrMagnitudeThreshold = 0.0001f;
28
-
29
-
30
-
28
+
29
+
30
+
31
- // キャラクターのTransform
31
+ // キャラクターのTransform
32
32
 
33
33
  public Transform player;
34
34
 
35
- // カメラの移動スピード
35
+ // カメラの移動スピード
36
36
 
37
37
  public float cameraMoveSpeed;
38
38
 
39
- // カメラの回転スピード
39
+ // カメラの回転スピード
40
40
 
41
41
  public float cameraRotateSpeed;
42
42
 
43
- // カメラのキャラクターからの相対値を指定
43
+ // カメラのキャラクターからの相対値を指定
44
44
 
45
45
  private Vector3 offset;
46
46
 
47
- // 追加...Start時のキャラクターに対するカメラの相対位置をプレイヤーのローカル座標系で保存
47
+ // Start時のキャラクターに対するカメラの相対位置をプレイヤーのローカル座標系で保存
48
48
 
49
49
  private Vector3 initialPlayerLocalOffset;
50
50
 
51
- // カメラの回転値を保存
51
+
52
-
53
- //Quaternion camRot; // 削除...今回は初期回転値を使わなかったので削除しました
52
+
54
-
55
- private Quaternion initialCamRotOffset; // 追加...プレイヤーの回転に対するカメラの相対回転値を保存
56
-
57
- private Vector3 cameraRight; // 追加...カメラの右方向
58
-
59
- private Vector3 cameraForward; // 追加...カメラの前方向
60
-
61
-
62
-
63
- public Vector3 CameraRight { get { return cameraRight; }} // 追加...プレイヤがカメラの右方向ために、プロパティとして公開
53
+ public Vector3 CameraRight { get; private set; } // 変更...バッキングフィルドとしてcameraRight用意すよりCameraRightをCameraControllerだけから設定可能なプロパティとした方がコードがシンプルになるかと思いました
64
-
54
+
65
- public Vector3 CameraForward { get { return cameraForward; }} // 追加...プレイヤーがカメラの前方向を知るために、プロパティとして公開
55
+ public Vector3 CameraForward { get; private set; } // 変更...CameraRightと同じくCameraControllerだけから設定可能なプロパティとしました
66
56
 
67
57
 
68
58
 
69
59
  bool flag = false;
70
60
 
71
- // float timer = 0; // 削除...回転終了判定を位置に基づいて行うことにしたので削除しました
72
-
73
61
 
74
62
 
75
63
  void Start ()
@@ -80,362 +68,238 @@
80
68
 
81
69
  offset = transform.position - player.position;
82
70
 
83
-
84
-
85
- //----初期位置・初期回転のパターン1----------------------------//
71
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
86
-
72
+
73
+
74
+
87
- initialPlayerLocalOffset = offset; // offsetをそのまま使うパターン...プレイヤーの初期回転角無視する
75
+ initialPlayerLocalOffset = player.InverseTransformDirection(offset); // offsetをプレイヤーローカル座標系に直すパターン採用
76
+
77
+
78
+
88
-
79
+ CameraRight = transform.right; // カメラの右方向を設定
80
+
81
+
82
+
83
+ var newForward = transform.forward; // 追加
84
+
85
+
86
+
87
+ newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
88
+
89
+ newForward.Normalize(); // 追加...正規化し長さを1に
90
+
91
+ CameraForward = newForward; // 変更...新しい前方向ベクトルを設定
92
+
93
+ }
94
+
95
+
96
+
97
+ void Update ()
98
+
99
+ {
100
+
101
+ //ALtキーを押すとカメラの位置をプレイヤーの真後ろへリセットする
102
+
103
+ if (Input.GetKeyDown (KeyCode.LeftAlt) || Input.GetKeyDown (KeyCode.RightAlt))
104
+
105
+ {
106
+
107
+ flag = true;
108
+
109
+ }
110
+
111
+ if (flag == true)
112
+
113
+ {
114
+
115
+ //プレイヤーの背後へ移動
116
+
117
+ Vector3 destinationOffset = player.TransformDirection(initialPlayerLocalOffset); // Start時にプレイヤーの座標系で見たカメラの位置を保存しておいたので、そこからカメラの目標オフセットを求める
118
+
119
+
120
+
121
+ // offset = Vector3.Slerp (offset, destinationOffset, cameraMoveSpeed * Time.deltaTime); // 変更...LerpをSlerpにして、カメラの動きが球面上の軌道を取るようにしてみました(Lerpの方がお好みでしたら、そちらでも問題ありません)
122
+
123
+ offset = InterpolateOffset(offset, destinationOffset, cameraMoveSpeed * Time.deltaTime); // 追加...Slerpの代わりにカスタム補間メソッドを使った場合
124
+
125
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
126
+
127
+ //回転が終わったら通常の追従状態に戻る?
128
+
129
+ if ((offset - destinationOffset).sqrMagnitude < CameraDeltaOffsetSqrMagnitudeThreshold)
130
+
131
+ {
132
+
133
+ offset = destinationOffset; // 目標オフセットに完全に移動する
134
+
135
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
136
+
89
- initialCamRotOffset = transform.rotation; // 同じく回転についてもプレイヤーの初期回転角無視する
137
+ CameraRight = transform.right; // カメラの右方向を更新、以後プレイヤーは新しい右方向基準に移動するようになる
138
+
139
+
140
+
90
-
141
+ var newForward = transform.forward; // 追加
142
+
143
+
144
+
145
+ newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
146
+
147
+ newForward.Normalize(); // 追加...正規化し長さを1に
148
+
91
- //--------------------------------------------------------//
149
+ CameraForward = newForward; // 変更...新しい前方向ベクトルを設定、以後プレイヤーは新しい前方向を基準に移動するようになる
150
+
151
+ flag = false;
152
+
153
+ }
154
+
155
+ }
156
+
157
+ transform.position = player.position + offset;
158
+
159
+ }
160
+
161
+
162
+
163
+ // 追加...offsetの補間用メソッド
164
+
165
+ static Vector3 InterpolateOffset(Vector3 a, Vector3 b, float t)
166
+
167
+ {
168
+
169
+ var aXZ = new Vector2(a.x, a.z); // 真上から見たa
170
+
171
+ var aR = aXZ.magnitude; // aのY軸からの距離
172
+
173
+ var aRIsNotZero = aR > 1E-05; // aRが(ほぼ)0より大きいか?
174
+
175
+ var aD = aRIsNotZero ? aXZ / aR : Vector2.zero; // 真上から見たaの方角、aRがほぼ0ならVector2.zeroとして無回転にする
176
+
177
+ var bXZ = new Vector2(b.x, b.z); // 真上から見たa
178
+
179
+ var bR = bXZ.magnitude; // bのY軸からの距離
180
+
181
+ var bD = (bR > 1E-05) ? bXZ / bR : Vector2.zero; // 真上から見たbの方角、bRがほぼ0ならVector2.zeroとして無回転にする
182
+
183
+ var theta = Mathf.Sign(aD.x * bD.y - bD.x * aD.y) * Mathf.Acos(Mathf.Clamp(Vector2.Dot(aD, bD), -1.0f, 1.0f)); // aDとbDがなす弧度法による符号付き角度
184
+
185
+ var alpha = aRIsNotZero ? Mathf.Atan2(aD.y, aD.x) : Mathf.Atan2(bD.y, bD.x); // 基準の角度...aDとX軸のなす角(aRがほぼ0ならbDとX軸のなす角)
186
+
187
+ var newTheta = Mathf.Lerp(0.0f, theta, t); // aDとbDがなす角度を線形補間
188
+
189
+ var newPhi = alpha + newTheta; // 基準の角度に先ほど線形補間した角度を足して、これを真上から見たときの新たな方角とする
190
+
191
+ var newR = Mathf.Lerp(aR, bR, t); // Y軸からの距離を線形補間
192
+
193
+ var newX = Mathf.Cos(newPhi) * newR; // 新しいX座標
194
+
195
+ var newY = Mathf.Lerp(a.y, b.y, t); // 新しいY座標(aとbのY座標を線形補間)
196
+
197
+ var newZ = Mathf.Sin(newPhi) * newR; // 新しいZ座標
198
+
199
+
200
+
201
+ return new Vector3(newX, newY, newZ);
202
+
203
+ }
204
+
205
+ }
206
+
207
+ ```
208
+
209
+
210
+
211
+ プレイヤーのスクリプト
212
+
213
+ ```C#
214
+
215
+ using UnityEngine;
216
+
217
+
218
+
219
+ public class PlayerController : MonoBehaviour
220
+
221
+ {
222
+
223
+ public CameraController cameraController; // 追加...カメラの右・前方向を知りたいので、カメラのスクリプトを保持するようにしました(インスペクタでカメラをセットしておいてください)
224
+
225
+
226
+
227
+ // Use this for initialization
228
+
229
+ private void Start()
230
+
231
+ {
232
+
233
+
234
+
235
+ }
236
+
237
+
238
+
239
+ // Update is called once per frame
240
+
241
+ private void Update()
242
+
243
+ {
244
+
245
+ float dirH, dirV;
246
+
247
+ float dirSpeed = 0.1f; // これは使用していないようですが、一応残しています
248
+
249
+ dirH = Input.GetAxis ("Horizontal");
250
+
251
+ dirV = Input.GetAxis ("Vertical");
252
+
253
+
254
+
255
+ // 削除...移動はvecを求めてから行う
92
256
 
93
257
  /*
94
258
 
95
- //----初期位置・初期回転のパターン2----------------------------//
96
-
97
- initialPlayerLocalOffset = player.InverseTransformDirection(offset); // offsetをプレイヤーローカル座標系に直すパターン...プレイヤーの初期回転角を考慮する
98
-
99
- initialCamRotOffset = Quaternion.Euler(0.0f, Mathf.DeltaAngle(player.eulerAngles.y, transform.eulerAngles.y), 0.0f); // ついでに、以前のコードでは相対回転が不適切だっだかもしれないと思い、Y軸周り回転の差だけを使うようにしました
100
-
101
- //--------------------------------------------------------//
259
+ transform.position = new Vector3 (transform.position.x - dirH * 0.1f, //横移動
260
+
261
+ transform.position.y,
262
+
263
+ transform.position.z - dirV * 0.1f); //奥移動
102
264
 
103
265
  */
104
266
 
267
+
268
+
105
- cameraRight = transform.right; // 追加...カメラ右方向を設定
269
+ var vec = cameraController.CameraRight * (dirH * 0.1f) + cameraController.CameraForward * (dirV * 0.1f); // 変更...入力された移動量について、水平はCameraRight、垂直はCameraForwardの向きへの移動と考え、これvecとする
106
-
270
+
271
+
272
+
107
- cameraForward = transform.forward; // 追加...カメラの前方向設定
273
+ transform.Translate(vec, Space.World); // 追加...位置vecだけ移動
108
-
109
- }
274
+
110
-
111
-
112
-
113
- void Update ()
275
+
114
-
115
- {
276
+
116
-
117
- //通常はプレイヤー位置一定距離を保って追従する
277
+ // 追加...立ち止まったときに初期向きってしまうのを防ぐため、入力がゼロ以外の時しか向きを回転しない
118
-
278
+
119
- /*
279
+ // カメラのスクリプトでやったのと同じく、vec.sqrMagnitudeが一定値未満かどうかで判定すれば、入力の有無の判定にあそびを設けることもできると思います
120
-
280
+
121
- if (flag == false)
281
+ if (vec != Vector3.zero)
122
282
 
123
283
  {
124
284
 
285
+ // ここから...
286
+
287
+ vec.Normalize ();
288
+
289
+ //方向を求める
290
+
291
+ var dirRot = Mathf.Atan2 (vec.x, vec.z) / 3.14159265f * 180.0f;
292
+
125
- transform.rotation = camRot; // 削除
293
+ transform.eulerAngles = new Vector3 (0.0f, dirRot, 0.0f);
126
-
294
+
127
- offset = transform.position - player.position; // 削除...毎回offsetを書き換えると、せっかく保存した相対位置が失われてしoffset更新はカメラ回転時のみ行うこにしした
295
+ // ここ代わりに下記ような回転方法もアリか思い
128
-
296
+
129
- transform.position = player.position + offset; // 削除...位置追従は最後に常に行うようにしました
297
+ // transform.rotation = Quaternion.FromToRotation(Vector3.forward, vec);
130
298
 
131
299
  }
132
300
 
133
- */
134
-
135
- //ALtキーを押すとカメラの位置をプレイヤーの真後ろへリセットする
136
-
137
- if (Input.GetKeyDown (KeyCode.LeftAlt) || Input.GetKeyDown (KeyCode.RightAlt))
138
-
139
- {
140
-
141
- flag = true;
142
-
143
- }
144
-
145
- if (flag == true)
146
-
147
- {
148
-
149
- // timer += Time.deltaTime; // 削除
150
-
151
- //プレイヤーの背後へ移動
152
-
153
- // transform.position = Vector3.Lerp (transform.position, player.position + (-player.forward * offset.z) + (Vector3.up * offset.y * 1.0f), cameraMoveSpeed * Time.deltaTime); // 削除...この時点では移動しないことにする
154
-
155
- Vector3 destinationOffset = player.TransformDirection(initialPlayerLocalOffset); // 追加...Start時にプレイヤーの座標系で見たカメラの位置を保存しておいたので、そこからカメラの目標オフセットを求める
156
-
157
- offset = Vector3.Lerp (offset, destinationOffset, cameraMoveSpeed * Time.deltaTime); // 追加...offsetを更新、ここでLerpを使いoffsetをなめらかに変えることにした
158
-
159
- //プレーヤーの方向へ回転
160
-
161
- Quaternion destinationRotation = player.rotation * initialCamRotOffset; // 追加...Start時にカメラの相対回転を保存しておいたので、そこからカメラの目標回転を求める
162
-
163
- transform.rotation = Quaternion.Slerp (transform.rotation, destinationRotation, cameraRotateSpeed * Time.deltaTime); // 変更
164
-
165
- //回転が終わったら通常の追従状態に戻る?
166
-
167
- if ((offset - destinationOffset).sqrMagnitude < CameraDeltaOffsetSqrMagnitudeThreshold) // (timer >= cameraRotateSpeed * Time.deltaTime) // 変更...回転終了の判定をoffsetとdestinationOffsetがほぼ一致したかで行うことにしました
168
-
169
- {
170
-
171
- // camRot = transform.rotation; // 削除
172
-
173
- offset = destinationOffset; // 追加...目標オフセットに完全に移動する
174
-
175
- transform.rotation = destinationRotation; // 追加...目標角度に完全に回転させる
176
-
177
- cameraRight = transform.right; // 追加...カメラの右方向を更新、以後プレイヤーは新しい右方向を基準に移動するようになる
178
-
179
- cameraForward = transform.forward; // 追加...カメラの前方向を更新、以後プレイヤーは新しい前方向を基準に移動するようになる
180
-
181
- // timer = 0; // 削除
182
-
183
- flag = false;
184
-
185
- }
186
-
187
- }
188
-
189
- transform.position = player.position + offset; // 追加...位置追従をこちらに引っ越し
190
-
191
- }
301
+ }
192
302
 
193
303
  }
194
304
 
195
305
  ```
196
-
197
-
198
-
199
- カメラのスクリプト(LookRotation版)
200
-
201
- ```C#
202
-
203
- using UnityEngine;
204
-
205
-
206
-
207
- public class CameraController : MonoBehaviour
208
-
209
- {
210
-
211
- private const float CameraDeltaOffsetSqrMagnitudeThreshold = 0.0001f;
212
-
213
-
214
-
215
- // キャラクターのTransform
216
-
217
- public Transform player;
218
-
219
- // カメラの移動スピード
220
-
221
- public float cameraMoveSpeed;
222
-
223
- // カメラの回転スピード
224
-
225
- public float cameraRotateSpeed;
226
-
227
- // カメラのキャラクターからの相対値を指定
228
-
229
- private Vector3 offset;
230
-
231
- // Start時のキャラクターに対するカメラの相対位置をプレイヤーのローカル座標系で保存
232
-
233
- private Vector3 initialPlayerLocalOffset;
234
-
235
-
236
-
237
- public Vector3 CameraRight { get; private set; } // 変更...バッキングフィールドとしてcameraRightを用意するより、CameraRightをCameraControllerだけから設定可能なプロパティとした方がコードがシンプルになるかと思いました
238
-
239
- public Vector3 CameraForward { get; private set; } // 変更...CameraRightと同じく、CameraControllerだけから設定可能なプロパティとしました
240
-
241
-
242
-
243
- bool flag = false;
244
-
245
-
246
-
247
- void Start ()
248
-
249
- {
250
-
251
- //プレイヤーとカメラの距離を計算する
252
-
253
- offset = transform.position - player.position;
254
-
255
- transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
256
-
257
-
258
-
259
- initialPlayerLocalOffset = player.InverseTransformDirection(offset); // offsetをプレイヤーローカル座標系に直すパターンを採用
260
-
261
-
262
-
263
- CameraRight = transform.right; // カメラの右方向を設定
264
-
265
-
266
-
267
- var newForward = transform.forward; // 追加
268
-
269
-
270
-
271
- newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
272
-
273
- newForward.Normalize(); // 追加...正規化し長さを1に
274
-
275
- CameraForward = newForward; // 変更...新しい前方向ベクトルを設定
276
-
277
- }
278
-
279
-
280
-
281
- void Update ()
282
-
283
- {
284
-
285
- //ALtキーを押すとカメラの位置をプレイヤーの真後ろへリセットする
286
-
287
- if (Input.GetKeyDown (KeyCode.LeftAlt) || Input.GetKeyDown (KeyCode.RightAlt))
288
-
289
- {
290
-
291
- flag = true;
292
-
293
- }
294
-
295
- if (flag == true)
296
-
297
- {
298
-
299
- //プレイヤーの背後へ移動
300
-
301
- Vector3 destinationOffset = player.TransformDirection(initialPlayerLocalOffset); // Start時にプレイヤーの座標系で見たカメラの位置を保存しておいたので、そこからカメラの目標オフセットを求める
302
-
303
- offset = Vector3.Slerp (offset, destinationOffset, cameraMoveSpeed * Time.deltaTime); // 変更...LerpをSlerpにして、カメラの動きが球面上の軌道を取るようにしてみました(Lerpの方がお好みでしたら、そちらでも問題ありません)
304
-
305
- transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
306
-
307
- //回転が終わったら通常の追従状態に戻る?
308
-
309
- if ((offset - destinationOffset).sqrMagnitude < CameraDeltaOffsetSqrMagnitudeThreshold)
310
-
311
- {
312
-
313
- offset = destinationOffset; // 目標オフセットに完全に移動する
314
-
315
- transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
316
-
317
- CameraRight = transform.right; // カメラの右方向を更新、以後プレイヤーは新しい右方向を基準に移動するようになる
318
-
319
-
320
-
321
- var newForward = transform.forward; // 追加
322
-
323
-
324
-
325
- newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
326
-
327
- newForward.Normalize(); // 追加...正規化し長さを1に
328
-
329
- CameraForward = newForward; // 変更...新しい前方向ベクトルを設定、以後プレイヤーは新しい前方向を基準に移動するようになる
330
-
331
- flag = false;
332
-
333
- }
334
-
335
- }
336
-
337
- transform.position = player.position + offset;
338
-
339
- }
340
-
341
- }
342
-
343
- ```
344
-
345
-
346
-
347
- プレイヤーのスクリプト
348
-
349
- ```C#
350
-
351
- using UnityEngine;
352
-
353
-
354
-
355
- public class PlayerController : MonoBehaviour
356
-
357
- {
358
-
359
- public CameraController cameraController; // 追加...カメラの右・前方向を知りたいので、カメラのスクリプトを保持するようにしました(インスペクタでカメラをセットしておいてください)
360
-
361
-
362
-
363
- // Use this for initialization
364
-
365
- private void Start()
366
-
367
- {
368
-
369
-
370
-
371
- }
372
-
373
-
374
-
375
- // Update is called once per frame
376
-
377
- private void Update()
378
-
379
- {
380
-
381
- float dirH, dirV;
382
-
383
- float dirSpeed = 0.1f; // これは使用していないようですが、一応残しています
384
-
385
- dirH = Input.GetAxis ("Horizontal");
386
-
387
- dirV = Input.GetAxis ("Vertical");
388
-
389
-
390
-
391
- // 削除...移動はvecを求めてから行う
392
-
393
- /*
394
-
395
- transform.position = new Vector3 (transform.position.x - dirH * 0.1f, //横移動
396
-
397
- transform.position.y,
398
-
399
- transform.position.z - dirV * 0.1f); //奥移動
400
-
401
- */
402
-
403
-
404
-
405
- var vec = cameraController.CameraRight * (dirH * 0.1f) + cameraController.CameraForward * (dirV * 0.1f); // 変更...入力された移動量について、水平はCameraRight、垂直はCameraForwardの向きへの移動と考え、これをvecとする
406
-
407
-
408
-
409
- transform.Translate(vec, Space.World); // 追加...位置をvecだけ移動
410
-
411
-
412
-
413
- // 追加...立ち止まったときに初期の向きに戻ってしまうのを防ぐため、入力がゼロ以外の時しか向きを回転しない
414
-
415
- // カメラのスクリプトでやったのと同じく、vec.sqrMagnitudeが一定値未満かどうかで判定すれば、入力の有無の判定にあそびを設けることもできると思います
416
-
417
- if (vec != Vector3.zero)
418
-
419
- {
420
-
421
- // ここから...
422
-
423
- vec.Normalize ();
424
-
425
- //方向を求める
426
-
427
- var dirRot = Mathf.Atan2 (vec.x, vec.z) / 3.14159265f * 180.0f;
428
-
429
- transform.eulerAngles = new Vector3 (0.0f, dirRot, 0.0f);
430
-
431
- // ここまでの代わりに、下記のような回転方法もアリかと思います
432
-
433
- // transform.rotation = Quaternion.FromToRotation(Vector3.forward, vec);
434
-
435
- }
436
-
437
- }
438
-
439
- }
440
-
441
- ```

2

LookRotationを使ったパターンを追記

2017/11/24 21:25

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -196,6 +196,154 @@
196
196
 
197
197
 
198
198
 
199
+ カメラのスクリプト(LookRotation版)
200
+
201
+ ```C#
202
+
203
+ using UnityEngine;
204
+
205
+
206
+
207
+ public class CameraController : MonoBehaviour
208
+
209
+ {
210
+
211
+ private const float CameraDeltaOffsetSqrMagnitudeThreshold = 0.0001f;
212
+
213
+
214
+
215
+ // キャラクターのTransform
216
+
217
+ public Transform player;
218
+
219
+ // カメラの移動スピード
220
+
221
+ public float cameraMoveSpeed;
222
+
223
+ // カメラの回転スピード
224
+
225
+ public float cameraRotateSpeed;
226
+
227
+ // カメラのキャラクターからの相対値を指定
228
+
229
+ private Vector3 offset;
230
+
231
+ // Start時のキャラクターに対するカメラの相対位置をプレイヤーのローカル座標系で保存
232
+
233
+ private Vector3 initialPlayerLocalOffset;
234
+
235
+
236
+
237
+ public Vector3 CameraRight { get; private set; } // 変更...バッキングフィールドとしてcameraRightを用意するより、CameraRightをCameraControllerだけから設定可能なプロパティとした方がコードがシンプルになるかと思いました
238
+
239
+ public Vector3 CameraForward { get; private set; } // 変更...CameraRightと同じく、CameraControllerだけから設定可能なプロパティとしました
240
+
241
+
242
+
243
+ bool flag = false;
244
+
245
+
246
+
247
+ void Start ()
248
+
249
+ {
250
+
251
+ //プレイヤーとカメラの距離を計算する
252
+
253
+ offset = transform.position - player.position;
254
+
255
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
256
+
257
+
258
+
259
+ initialPlayerLocalOffset = player.InverseTransformDirection(offset); // offsetをプレイヤーローカル座標系に直すパターンを採用
260
+
261
+
262
+
263
+ CameraRight = transform.right; // カメラの右方向を設定
264
+
265
+
266
+
267
+ var newForward = transform.forward; // 追加
268
+
269
+
270
+
271
+ newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
272
+
273
+ newForward.Normalize(); // 追加...正規化し長さを1に
274
+
275
+ CameraForward = newForward; // 変更...新しい前方向ベクトルを設定
276
+
277
+ }
278
+
279
+
280
+
281
+ void Update ()
282
+
283
+ {
284
+
285
+ //ALtキーを押すとカメラの位置をプレイヤーの真後ろへリセットする
286
+
287
+ if (Input.GetKeyDown (KeyCode.LeftAlt) || Input.GetKeyDown (KeyCode.RightAlt))
288
+
289
+ {
290
+
291
+ flag = true;
292
+
293
+ }
294
+
295
+ if (flag == true)
296
+
297
+ {
298
+
299
+ //プレイヤーの背後へ移動
300
+
301
+ Vector3 destinationOffset = player.TransformDirection(initialPlayerLocalOffset); // Start時にプレイヤーの座標系で見たカメラの位置を保存しておいたので、そこからカメラの目標オフセットを求める
302
+
303
+ offset = Vector3.Slerp (offset, destinationOffset, cameraMoveSpeed * Time.deltaTime); // 変更...LerpをSlerpにして、カメラの動きが球面上の軌道を取るようにしてみました(Lerpの方がお好みでしたら、そちらでも問題ありません)
304
+
305
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
306
+
307
+ //回転が終わったら通常の追従状態に戻る?
308
+
309
+ if ((offset - destinationOffset).sqrMagnitude < CameraDeltaOffsetSqrMagnitudeThreshold)
310
+
311
+ {
312
+
313
+ offset = destinationOffset; // 目標オフセットに完全に移動する
314
+
315
+ transform.rotation = Quaternion.LookRotation(-offset); // offsetが更新されたので、カメラ回転も更新
316
+
317
+ CameraRight = transform.right; // カメラの右方向を更新、以後プレイヤーは新しい右方向を基準に移動するようになる
318
+
319
+
320
+
321
+ var newForward = transform.forward; // 追加
322
+
323
+
324
+
325
+ newForward.y = 0.0f; // 追加...カメラの前方向をXZ平面上に投影
326
+
327
+ newForward.Normalize(); // 追加...正規化し長さを1に
328
+
329
+ CameraForward = newForward; // 変更...新しい前方向ベクトルを設定、以後プレイヤーは新しい前方向を基準に移動するようになる
330
+
331
+ flag = false;
332
+
333
+ }
334
+
335
+ }
336
+
337
+ transform.position = player.position + offset;
338
+
339
+ }
340
+
341
+ }
342
+
343
+ ```
344
+
345
+
346
+
199
347
  プレイヤーのスクリプト
200
348
 
201
349
  ```C#

1

カメラ初期位置・初期回転を修正

2017/11/24 13:35

投稿

Bongo
Bongo

スコア10807

test CHANGED
@@ -52,7 +52,7 @@
52
52
 
53
53
  //Quaternion camRot; // 削除...今回は初期回転値を使わなかったので削除しました
54
54
 
55
- Quaternion initialCamRotOffset; // 追加...プレイヤーの回転に対するカメラの相対回転値を保存
55
+ private Quaternion initialCamRotOffset; // 追加...プレイヤーの回転に対するカメラの相対回転値を保存
56
56
 
57
57
  private Vector3 cameraRight; // 追加...カメラの右方向
58
58
 
@@ -80,17 +80,27 @@
80
80
 
81
81
  offset = transform.position - player.position;
82
82
 
83
+
84
+
85
+ //----初期位置・初期回転のパターン1----------------------------//
86
+
87
+ initialPlayerLocalOffset = offset; // offsetをそのまま使うパターン...プレイヤーの初期回転角を無視する
88
+
89
+ initialCamRotOffset = transform.rotation; // 同じく回転についてもプレイヤーの初期回転角を無視する
90
+
91
+ //--------------------------------------------------------//
92
+
93
+ /*
94
+
95
+ //----初期位置・初期回転のパターン2----------------------------//
96
+
83
- initialPlayerLocalOffset = player.InverseTransformDirection(offset); // 追加...この時点のoffsetをプレイヤーローカル座標系に直して、これ覚えておく
97
+ initialPlayerLocalOffset = player.InverseTransformDirection(offset); // offsetをプレイヤーローカル座標系に直すパターン...プレイヤーの初期回転角考慮する
84
-
85
- //距離分離す
98
+
86
-
87
- // transform.position = player.position + offset; // 削除...この時点ではカメラは適切な位置にいるのだから、あらためて設定する必要はないように思います
88
-
89
- //初期回転値を保存
90
-
91
- // camRot = transform.rotation; // 削除
92
-
93
- initialCamRotOffset = Quaternion.RotateTowards(player.rotation, transform.rotation, 180.0f); //追加...プレイヤーの回転対するカメラの相対回転保存
99
+ initialCamRotOffset = Quaternion.Euler(0.0f, Mathf.DeltaAngle(player.eulerAngles.y, transform.eulerAngles.y), 0.0f); // ついで、以前コードでは相対回転が不適切だっだかもしれないと思い、Y軸周り回転の差だけ使うようにしました
100
+
101
+ //--------------------------------------------------------//
102
+
103
+ */
94
104
 
95
105
  cameraRight = transform.right; // 追加...カメラの右方向を設定
96
106
 
@@ -182,8 +192,6 @@
182
192
 
183
193
  }
184
194
 
185
-
186
-
187
195
  ```
188
196
 
189
197
 
@@ -282,6 +290,4 @@
282
290
 
283
291
  }
284
292
 
285
-
286
-
287
293
  ```