Unityで操作キャラクターの回りを旋回する攻撃ユニットの作成 | Unityを使った3Dゲームの作り方(かめくめ)

Unityで操作キャラクターの回りを旋回する攻撃ユニットの作成

今回は操作キャラクターの回りを旋回する弾を発射する攻撃ユニットの作成をしていきたいと思います。

キャラクターを移動させてもキャラクターの回りをグルグル回り、ユニットの攻撃ボタンを押したらユニットが向いている方向(キャラクターからユニットを見た方向)に弾を飛ばすようにしたいと思います。

今回の機能を作成すると、

上のようになります。

シューティングゲームやアクションゲーム等で使えそうですね。(^^)v

スポンサーリンク

攻撃ユニットの作成

それでは攻撃ユニットの作成をしていきましょう。

ユニットゲームオブジェクトの作成

今回はユニットをUnityのCubeで作成していきます。

ヒエラルキー上で右クリックから3D Object→Cubeを選択し、名前をUnitとします。

次にUnit用のマテリアルを作成します。

Assetsエリア内で右クリックからCreate→Materialを選択し、名前をUnitMaterialとします。

UnitMaterialを選択し、インスペクタのAlbedoの色を赤色にします。

攻撃ユニット用マテリアル

UnitMaterialをヒエラルキー上のUnitにドラッグ&ドロップするか、UnitのインスペクタのMeshRendererのMaterialsのElement 0にUnitMaterialをドラッグ&ドロップします。

マテリアルが適用されるとUnitが赤色になります。

デフォルトのCubeだとユニットとしては大きいのでTransformのScaleを0.3にし少し小さくします。

また、ユニットが他のゲームオブジェクトと衝突すると困るのでUnitのBox Colliderコンポーネントを削除します(Box Colliderの右の歯車からRemove Component)。

これでUnitのインスペクタは

攻撃ユニットのサイズ調整とマテリアルの適用

上のようになります。

これでユニットのゲームオブジェクトが出来ました。

ユニットがキャラクター回りを旋回するスクリプト

ユニットが出来たので、次は操作キャラクターの回りを旋回するようにスクリプトを作成していきます。

ユニットが操作キャラクターの回りをグルグル回るスクリプトは

Unityのゲームで使用するキャラクターの移動やカメラの回転、カメラのズーム機能、カメラの壁対策、人との会話、敵を攻撃等のすべてをマウス操作で行う為の機能を作成していきます。

の記事で作成したキャラクターの回りをカメラが回る機能と同じようにして作成します。

つまりカメラをユニットに置き換えて計算していくことになります。

ユニットの位置 = 操作キャラクターの位置 + 操作キャラクターの位置とユニットのある位置の角度 × 操作キャラクターからユニットまでのベクトル

という計算式を使います。

計算式を見ると分かり辛いですが、まず操作キャラクターの位置を中心として、そこからユニットがある位置を計算します。

ユニットの角度はUpdateメソッドが呼ばれる度に少しづつ角度を変化させます。

というわけでそれを元にスクリプトを作成しUnitに取り付けます。

ユニットが旋回するターゲットはインスペクタで設定出来るようにしておきます。

angleはキャラクターから見たユニットの角度を入れます。

rotateSpeedはユニットが1秒間に回転する角度を指定します。

ターゲットからの距離はtargetに設定した操作キャラクターからユニットまでの距離をベクトルで指定し、ユニットの位置をインスペクタで設定出来るようにしています。

Updateメソッド内が実際にユニットの位置を作成している処理です。

ターゲットから見たユニットの角度はQuaternion.Eulerを使ってオイラー角を指定しますが、ターゲットを中心にY軸で回転させる為にY軸にangleを指定し、X軸とZ軸は0で固定にします。

ユニットの位置はこれで出来ましたがこの後、弾を飛ばす時にユニット自身の角度をキャラクターから見たユニットの方向に向けさせておく必要があります。

なので、ユニットの位置からターゲットの位置を引いてユニットの方向を求め、Quaternion.LookRotationを使ってVector3.up(Y軸)を軸にして角度を求め、それをユニット自身の角度とします。

その後angleを回転スピード分足します。

角度は0~360の間で収めたいのでMathf.Repeatを使っています。

これで操作キャラクターの回りをグルグル回るユニットが出来ました。

ユニット位置の計算を実際に試して理解する

ユニットの位置や角度の計算式が分かり辛い方は実際にゲームオブジェクトを設置して試してみるとわかりやすいかもしれません。

例えばCubeをヒエラルキー上に配置しスクリプトを取り付けます。

上のスクリプトではインスペクタで設定したターゲットの位置にCubeが来るだけです。

ユニットをターゲットの位置に移動

上の画像では右上のCubeが最初にCubeを配置した位置で、キャラクターをtargetにしているのでキャラクターの足元にあるのがこのスクリプトを設定したCubeの位置です。

次にY軸で45度回転しベクトルをかけてユニットの位置を計算する処理を足します。

Quaternion.Euler(0f, 45f, 0f)でY軸で45度回転しそれにnew Vector3(0f, 0f, Mathf.Sqrt(2))をかけることでその角度の前方に√2の長さの位置にターゲットの位置を足してユニットの位置を求めます。

前方にルート2としているのは三平方の定理で横と縦が1だと斜め方向の長さがルート2となるのでUnityのシーンビュー上で丁度スリットの真ん中にCubeがくるようにしたかった為です。

実行すると、

ユニットの位置の計算をわかりやすくした図

上のようになります。

上のCubeが元の位置でXYZが(1, 1, 1)の位置に置いてあります。

下のCubeがスクリプトで計算した位置でターゲットであるキャラクターの位置からY軸で45度回転し、その方向のベクトルにルート2の長さ分移動したものです。

ユニット自身の角度を実際に試して理解する

次はユニット自身の角度をキャラクターからユニットの位置の方向に向けるのを実際に試して確認してみます。

上のスクリプトではVector3.forwardでワールド空間の前方(Z軸)の方向-を付けて反転させ、Vector3.up(Y軸)を軸にした角度をQuaternion.LookRotationで計算しています。

ユニット自身の角度を変える為のわかりやすい画像

上のように上のCubeは元の角度なのでデフォルトのままワールドのZ軸と同じ方向を向き、下のCubeはスクリプト計算して角度をワールドのZ軸の反対側にしています。

ユニット自身の角度の計算が出来たところで、次はキャラクターからユニットの方向を求めその角度をユニットの角度に設定すればユニット自身の角度がそちらの方向を向いてくれます。

キャラクターからユニットの方向を求めるには

ユニットの位置 – キャラクターの位置

を計算すると求められますので、

上のようになります。

ユニットとキャラクターのY軸の位置が違うと向く方向が変わってしまうので、キャラクターの位置のY軸をユニットのY軸と同じにして計算します。

ユニット自身の角度計算のわかりやすい画像

上のようにユニット自身の前方(ローカルのZ軸)がキャラクターからユニットの方向になっているのがわかります。

ユニットが攻撃出来るようにするスクリプト

ユニットが操作キャラクターの回りをグルグル回るようになったので、次はユニットの攻撃ボタンを押したらユニットが向いている方向に弾を飛ばす処理を作成していきます。

RotateUnitスクリプトに追記していきます。

弾のプレハブ、弾を飛ばす力をインスペクタで設定出来るようにします。

Updateメソッド内でFire1に設定したボタンを押した時に弾のプレハブからインスタンスを生成しています。

弾の生成位置はユニットの位置と角度にします。

弾のインスタンスに設定しているRigidbodyコンポーネントを取得しAddForceメソッドでユニットの前方(transform.forward)に力を加えて飛ばします。

ここら辺の処理は

Unityのガンシューティングゲームなどで銃から弾を飛ばす場合にスクリプトで敵と接触したか判断するのではなく、物理的な弾を飛ばしその弾が当たったかどうかで判断させます

の記事あたりと同じですね。

弾のプレハブの作成

弾のプレハブはヒエラルキー上に右クリックから3D Object→Sphereを選択し、名前をBulletとし、インスペクタのAdd ComponentからPhysics→Rigidbodyを取り付けUse Gravityのチェックを外し重力が働かないようにします。

またユニットのサイズに応じて出てくる弾のサイズも調整しておきます。

弾のプレハブのインスペクタの設定

後はBulletをAssetsエリア内にドラッグ&ドロップしてプレハブにし、RotateUnitのbulletに設定します。

キャラクターを旋回する攻撃ユニットの完成

キャラクターの回りを旋回する攻撃ユニットが出来上がりましたので、ユニットを幾つか配置し設定を変えて試してみましょう。

上のようになりました。

上の例ではユニットを4つ配置しそれぞれのインスペクタでユニットのY軸の角度であるangleの初期値をインスペクタで変えてユニットが同じ位置にこないようにしています。

angleはそれぞれ0、90、180、270を設定しています。

終わりに

今回の攻撃ユニットはY軸で回転していますが、スクリプトの角度の部分を変えることで縦回転や不思議な回転にする事も出来ます。

今回の場合はターゲットのY軸の位置とユニットのY軸の位置を合わせて地面に平行に弾が飛ぶようにしていますが、Y軸を合わせないでも良いなら

上のように回転軸をインスペクタで設定出来るようにし、

上のように回転軸であるaxisOfRotationにangleをかける形にして、ユニット自身の角度を作る時にY軸の位置を合わせた計算をしないようにします。

上の例では一括でaxisOfRotationにangleをかけてますが、Vector3のXYZのそれぞれの角度を更新する事も出来ます。

こうすると色々面白い動きをするユニットが出来るかも?しれません。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます

コメント

  1. まつかぜはぐるま より:

    すいませんunityでのsendinputについて詳しく教えてください。
    マクロが作成したいです。