Unity_udemy_3d_shooting
Git管理
リポジトリをクローンする
Unityでプロジェクト作成
作成したプロジェクトを、Unityを閉じてからコピーする
gitignoreの階層に、Asset等を全部コピーしていれる
Unity Hubで、そのgit管理するリポジトリをaddすればよい
クラッシュコースを流し見しておく
Unity 2022.3 LTSで作業を進める
3d build in render pipelineでproject作成
覚えておくと良さそうなこと
alt + 左クリックで視点だけ動かす
towerとgunで、組み合わせた時中心を軸に回ってしまう
https://scrapbox.io/files/695b485a56802837a94c411b.png
x,y,z
x: 水平方向に移動(いわゆる左右)
y: 上下の縦に移動
z: 前進と後退
object挙動
グローバル軸ではなく、Local軸でとらえる。そのオブジェクトにとっての前方が、どの軸になるのかを考える。
マウスポインタの場所をつかむ
code:c#
Debug.Log(Input.mousePosition);
これでもできるが、グローバルな座標が表示される。なので、戦車から見てどのポジションにマウスがあるかを把握したい。
Input.mousePositionは画面上の座標なので、2次元の座標。奥行きを取りたいので、まずRay ray = Camera.main.ScreenPointToRay(Input.mousePosition);とすることでカメラから見た3D空間の方向を取得できる。(カメラからマウス位置に向かってRaycastを射出している)
Physics.Raycast(ray, out hit, Mathf.Infinity, whatIsAimMask)で、Rayが何に当たったかを検知し、その検知した場所の座標を返している
ポインタの位置に近づける
code:c#
private void FixedUpdate()
{
Vector3 movement = transform.forward * moveSpeed * verticalInput;
rb.velocity = movement;
transform.Rotate(0, horizontalInput * rotationSpeed, 0);
Vector3 direction = aimTransform.position - towerTransform.position;
direction.y = 0;
Quaternion targetRotation = Quaternion.LookRotation(direction);
towerTransform.rotation = Quaternion.RotateTowards(towerTransform.rotation, targetRotation, towerRotationSpeed);
}
旧Inputシステム
code:c#
if(Input.GetButtonDown("Fire1"))
Shoot();
この辺りの挙動は、Project Settingで調整ができる。
https://scrapbox.io/files/695b6de500280c37d9985144.png
KeyCodeでやるのが無難。
New Input System
https://scrapbox.io/files/695b8805b07c4657968e1bf8.png
アセットストア > Unity Registryのものを使う。install
両方の入力を許可しておく。edit > project setting > player > Configuration
https://scrapbox.io/files/695b886187375d32438e3c77.png
設定し終わったら、Generate C# classでスクリプト生成
Character Controllerコンポーネントと入力
入力について
public Vector3 movementDirection;という定義がある。これはx軸が水平移動でz軸が前後移動を示すので、基本的にx軸とz軸で定義していく。InputSystemで移動をVector2で取得したなら、水平はx, 前後はyとして充てればよいので、movementDirection = new Vector3(moveInput.x, 0, moveInput.y);という感じにあてればよい
Character Controllerコンポーネントを充てていれば、
値を渡してやるだけで基本的な移動処理をやってくれる。characterController.Move(movementDirection * Time.deltaTime * walkSpeed);という感じで。
isGrounded等も用意されている。コライダーとかも。
リグについて
モデルを動かす場合に、少ない編集箇所で直感的に動作をつけるために作られたコントローラ、また動かす仕組みのこと
mixamoを使って、動かせるようにしよう
すごい
アニメーション
2Dと同じコントローラの割当
Avatarの割当
デフォルトのスプライトみたいなもの
落としてきたリグをのAnimation TypeをHumanoidと設定してApply。その後、Animationタブでも調整が必要。
loopをON
青い矢印が前を表すが、その方向に合わせてモデルを調整。Bake Into Poseにチェックを入れて、Originalを設定。Apply。こでもうまくいかなければ、Offsetで調整。
https://scrapbox.io/files/695ccd861a274bec515bd0a9.png
左右前後の移動をBlend Treeで分割しよう
パラメータを用意するとたまにNahエラーに発生するので、その場合は再起動するとよい
内積とAnimation Parameter
code:c#
private void AnimatorController()
{
float xVelocity = Vector3.Dot(movementDirection.normalized, transform.right);
float zVelocity = Vector3.Dot(movementDirection.normalized, transform.forward);
animator.SetFloat("xVelocity", xVelocity, .1f, Time.deltaTime);
animator.SetFloat("zVelocity", zVelocity, .1f, Time.deltaTime);
}
ベクトル
movementDirection.normalized
移動の向きだけ取得(長さ1のベクトル)
transform.right / forward
キャラクタ基準の右と前の座標(ローカルx+と、ローカルz+)のこと
つまりキャラが回ると、この軸も回る
Vector3.Dot(a,b)
aとbの内積。cosθはベクトルa・ベクトルb / |a| |b|で求められる。
単位ベクトル同士の場合、分母が1なので、結果的にcosθが返る。
つまり -1 : 180°(真逆) 0: 90°(直交) +1: 0°(真正面) という結果になる
xVelocity
移動方向と右向きを比較。
1なら完全に右向き 0なら右でも左でもない(右軸に直交) -1なら左向きであることを示す
zVelocity
移動方向と前向きを比較。
1なら完全に真正面 0なら前でも後ろでもない(左軸に直交) -1なら後ろ向きであることを示す値となる。
リロードを作る
上半身だけの動きをブレンドする
アニメーションレイヤーを新規に作って、銃を撃つ挙動を管理する。FIreのモーションがあるが、それを複製し、最初の銃を構えているフレームだけを銃を構えるidleとして扱うようにした。それを新規のアニメレイヤーにドラックして、まず持ってくる
https://scrapbox.io/files/695e22ca894e311753d71907.png
こんな感じで、銃はどんなstateでも(Any Stateでも)、銃を撃つボタンさえ押されれば動くようにする。
レイヤーの優先度
BaseLayerとWeaponの重みが現在1と0なので、BaseLayerの動きが優先される(つまり射撃アニメを作っても、反映されない)。なので、Weapon側の重みも追加してやるのが良い。
すると今度は足が動かなくなるので、Avatar Maskを用意する(体のどの部分を動かすかをある程度決めることができるアセット)。下半身を動かなくさせて、それをWeapon Layerに割り当てる。するとBaseLayerの足の動きのまま、射撃時はWeaponレイヤーの上半身の挙動を実現することができる。
Animation Rigging
特定のものを、指定したものに向けるようにする処理
たとえばNPCキャラがプレイヤーの方向を向くなど。
multi aim constraint
メインアニメーションのボーンの動きを制御できる(オーバーライドして制御するようになる)
左手を銃に沿える
Rigに、LeftHand_IKというオブジェクトを追加。Two Bone IK Constraintを付与。身体の特定部分のボーンの配置を調整できる
Rigに従って手が添えられる(中略)が、そのRIgの位置を所持している武器によって上書きするようなスクリプトを書いてやればできる。
使うアニメを分ける
ショットガンにはショットガンの、SRにはSRのアニメをFireしたときに使いたい。
通常移動と武器レイヤーは、重みを同じにして活用している。なので、使う武器のレイヤーの重みを1にして、そうでない武器レイヤーの重みは0にするように調整すればよい。
アニメーションレイヤーのsync
同じ条件や分岐を使えるが、実際のアニメは異なる挙動にすることができる
これで、リロード処理とかそういったものを加えるときも全てに適用ができる
リロードのanimation
AnyStateから遷移できる。リロード->リロードはできないようにしたいので、Can Transition to self をオフにする。打った瞬間にリロードでキャンセルできないように、Transition Durationを軽く持たせる。
実際に動作させると、リグで左手を銃に沿えるように設計しているので、手がうまく動かない。(リグの重みを調整すれば調整が可能になる)。なので、リロードが終わったらtime.deltatimeで重みを増やすような形にすればスムーズに移行する。
リロードアニメへのイベントトリガー追加
ReadOnlyでアニメが作られている場合、編集ができない。duplicateしてそのアニメを割り当て直し、編集していく。
武器切り替えアニメ
軽めの武器はsideから、重めの武器はbackから取る動きにする。リロードとファイアは切り替え中はできなくしたいので、transitionに武器切り替え中かどうかを判定するフラグを条件を追加しておく。2パターンのアニメは今回ブレンドツリーで実装する(武器タイプが0ならsideから、1ならbackから取る)。レイヤーをsyncしていても、Blend Treeの内容は共有されないのでそこだけ注意。1つずつ対応する。
カメラ
同じく、Cinemachineを使う。Unity Registryにあるのでインストールしよう。
Cinemachine > VIrtual Camera。Cinemachineのカメラはメインカメラを常にoverrideする。
プレイヤーの回転速度の調整
基本的に回転を表現するときは、Quaternionが伴うケースが多い(ここで線形代数を使った処理が内部で動く)。
Prefabを用いて弾丸を実装する
Trail Rendererを弾に設定すれば、弾の軌道を可視化できる
0.0に近い値で調整して、Materialで色をつけると軌跡を追える。
設定後は弾丸同士、弾丸とプレイヤーが衝突しないようにレイヤーで分け、Project Setting > Physicsで Layer Collision Matrixで調整。
ターゲット処理
マウスポインタのRaycastで拾った要素にComponentが付与されていたら、エイム位置をそのオブジェクトのtransformにする形で落とし込める
Colliderを膨らませると、ターゲットへのエイムを緩和できる。その場合は大きめの判定を親のColliderで設定してisTriggerとし、実際の当たり判定は子要素に別のColliderとして持たせて運用するとよい。
エイムの可視化
Line Rendererを使う。
Time.deltaTime
やること
とりあえずブロック崩しみたいな簡単なゲームを用意
数学でベクトル使ったものをコードにしてみる
やってないことやってみる
セーブ
NPCにしゃべらせる