• トップ
  • ブログ一覧
  • 【Unity】アクションゲームにおけるキャラクターの移動方法
  • 【Unity】アクションゲームにおけるキャラクターの移動方法

    メディアチームメディアチーム
    2020.03.26

    IT技術

    アクションゲームには「移動」が不可欠

    コンピューターゲームが誕生し今日までに、「スーパーマリオブラザーズ」などの沢山のアクションゲームが生み出されてきました。

    「Unity(ユニティ)」を扱っている方であれば、そういったアクションゲームを「作ってみたい!」と考えた事があるのではないでしょうか。

    しかし、1からアクションゲームを作るにも、作業量の多さに、しり込みしてしまった方も多いと思いのでは?

    実際、素材集めから自力でやると、どうしても完成まで時間がかかってしまいます。

    キャラクターの移動からアクションゲームを作る

    ただし、1つ1つの工程を焦らずにしっかりと作りこめば、思ったより簡単にアクションゲームを作ることが可能なのです!

    今回は、まず初めに実装すべき「キャラクターの移動」について解説していきます。

    Transformによる操作

    Unity で物体を動かすには、様々な方法があります。

    それらを分類すると、大きく分けて2通りあります。

    Transform による移動

    1つ目は「Transform による移動」です。

    Transform による移動では、直接位置情報を制御します。

    つまり、外部から力が加えられて物体が移動するのではなく、物体が細かいワープを繰り返しているイメージになります。

    したがって、Transform で移動をしようとしたとき、当たり判定を通過してしまう場合もあります。

    さらには、当たり判定を用いた状態での Transform による移動は、処理が重くなってしまいます。

    Transform の利点

    こうやってみると、Transform による移動にはメリットがないように見えてしまいます。

    しかし、物理演算に影響されないという大きな利点があるのです。

    「2段ジャンプ」であったり「空中ダッシュ」であったりと、機動性の高いアクションは物理演算が関わってくるとうまく再現できません。

    アクション性に富んだゲームを制作するのであれば、Transform による操作を選択することをオススメします!

    物理エンジンによる操作

    Transform による移動では、物理演算が反映されません。

    では、どのようにして物理演算を反映させた状態で物体を移動すればいいのでしょうか。

    Rigidbodyによる移動

    そのときは、2つ目の「Rigidbody」が用いられます。

    Rigidbody では、外部から力が加えられて物体が移動します

    Transform による移動に比べて、滑らかな動きになります。

    ですが、重力や摩擦などが関わってくるため、簡単な移動を行う場合でも、正しく理解していないと不自然な動きになってしまいます。

    Rigidbody による移動の中にも、いくつかの種類があります。

    AddForceを使った移動

    「AddForce メソッド」はオブジェクトに物理的な力を加えて移動させる関数です。

    「車がアクセルを踏んで加速したり」「ボールを蹴飛ばしたり」といった、力学的な動きが自然に再現できます。

    つまり、物理演算を使用し、オブジェクトを現実に近い動きで動かしたいときに使う方法です。

    AddForce には、4つ「ForceMode」があり、それぞれ違った物理挙動を示します。

    ForceMode.Force:継続的に力を加える

    「ForceMode.Force」はオブジェクトに力を継続的に加えていきます

    アクセルを踏み続けると車が加速していくように、力を加えている間オブジェクトの移動速度は加速していきます。

    下の画像は、常に「Force」の「AddForce」を与え続けた例です。

    オブジェクトが徐々に加速しているのがわかります。

    スクリプト

    スクリプトは下記のようになります。

    1//Forceでキューブを動かすスクリプト
    2public Rigidbody rb;
    3
    4void Start() {
    5    // Rigidbodyコンポーネントを取得する
    6    rb = GetComponent<Rigidbody>();
    7}
    8
    9void FixedUpdate() {
    10    rb.AddForce(0, 15.0f, 0, ForceMode.Force);
    11}

    ForceMode.Accelaration:質量を無視して継続的に力を加える

    ForceMode.Accelaration」は「Force」同様、オブジェクトに力を継続的に加えます

    Force との違いはオブジェクトの質量に影響されないという点です。

    動きの比較

    下の画像のように、Force で力を加えた場合は、質量の違いが加速度の違いに表れています。

    しかし、Accelaration の場合は下の画像のように、質量が違っていても同じ加速度になります。

    重いオブジェクトであろうと、軽いオブジェクトであろうと同じように動かしたい時などに使用されます。

    スクリプト

    スクリプトは下記のようになります。

    1// Accelarationでキューブを動かすスクリプト
    2public Rigidbody rb;
    3
    4void Start() {
    5    // Rigidbodyコンポーネントを取得する
    6    rb = GetComponent<Rigidbody>();
    7}
    8
    9void FixedUpdate() {
    10    rb.AddForce(0, 15.0f, 0, ForceMode.Accelaration);
    11}

     

    ForceMode.Impulse:瞬間的に力を加える

    「ForceMode.Impulse」は上記の二つとは違って、瞬間的にオブジェクトに力を加えて動かす方法です

    「おはじきをはじく」「ボールを蹴る」といった事をイメージをすると分かりやすいかもしれません。

    上の画像は、上向きに一度だけ「Impulse」の「AddForce」を与えているものです。

    ボールを蹴り上げているようにオブジェクトが動きます。

    スクリプト

    スクリプトは下記のようになります。

    1// Impulseでキューブを動かすスクリプト
    2void Start() {
    3    GetComponent<Rigidbody>().AddForce(0, 5.0f, 0, ForceMode.Impulse);
    4}

    ForceMode.VelocityChange:質量を無視して瞬間的に力を加える

    「ForceMode.VelocityChange」は、Impulse と同様に瞬間的にオブジェクトに力を加えます。

    しかし、Impulseとは違い質量によってオブジェクトの動きが変わることがありません

    動きの比較

    下の画像は、Impulse を違う質量のオブジェクトに与えた時の動きです。

    下の画像は、VelocityChange を違う質量のオブジェクトに与えた時の動きです。

    Impulse では質量によって飛んでいる高さが変わっておりますが、VelocityChangeでは同じ高さまで飛んでいることがわかります。

    こちらも Accelaration 同様、違う質量のオブジェクトで同じ動きをさせたいときに用いられます

    スクリプト

    スクリプトは下記のようになります。

    1// VelocityChangeでキューブを動かすスクリプト
    2void Start() {
    3    GetComponent<Rigidbody>().AddForce(0, 5.0f, 0, ForceMode.VelocityChange);
    4}

    positionを使った移動

    rigidbody.position」を直接書き換えることによって、座標を上書きして瞬間的に移動します

    この方法は「transform.position」と同様に、座標を直接操作する移動方法です。

    したがって、当たり判定や物理演算がなく、座標を強制的に変更します

    普段の移動に使うというよりも、座標の初期値を設定したり、強制的に場所を移動させる際に使うと良いでしょう。

    下の画像は、rigidbody.position でオブジェクトを動かしておりますが、ボールが回転せずスライドしており、自然な物理演算が行われていません。

    スクリプト

    スクリプトは下記のようになります。

    1// rigidbody.positionでキューブを動かすスクリプト
    2public Rigidbody rb;
    3
    4void Start() {
    5    // Rigidbodyコンポーネントを取得する
    6    rb = GetComponent<Rigidbody>();
    7}
    8
    9void FixedUpdate() {
    10    // 座標を取得
    11    Vector3 now = rb.position;
    12    // 前に少しずつ移動するように加算
    13    now += new Vector3 (0.0f,0.0f,0.05f); 
    14    // 値を設定
    15    rb.position = now; 
    16}

    velocityを使った移動

    「rigidbody.velocity」を使うと、速度ベクトルの取得・保持が可能になります

    しかし、「velocity」を直接変更することは基本推奨されておりません。

    理由としては、力や質量などを計算に加えずに突然速度が変化するため。現実の物理的な動きから外れてしまう点があります。

    一方で、ベクトルの力、すなわち速度を取得することができるため、「Textでレースゲームのスピード表示」に用いたり、「速度制限」に用いたりすることができます

    さいごに

    いかがでしたでしょうか。

    今回は、アクションゲームにおけるキャラクターの移動について、様々な方法を紹介しました。

    それぞれの方法に一長一短があり、自分が作りたいものによって実装すべき方法が変わってきます。

    ご紹介したいくつかの方法を試してみて、自分の作品にあったものを選択して実装していきましょう。

    こちらの記事もオススメ!

    featureImg2020.07.17ライトコード的「やってみた!」シリーズ「やってみた!」を集めました!(株)ライトコードが今まで作ってきた「やってみた!」記事を集めてみました!※作成日が新し...

    featureImg2020.07.28Unity 特集知識編おすすめのゲームエンジン5選実装編※最新記事順に並べています。VR環境でテキストを表示する方法非同期式の入れ子処...

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    メディアチーム
    メディアチーム
    Show more...

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background