ひとりでのアプリ開発 - fineの備忘録 -

ひとりでアプリ開発をするなかで起こったことや学んだことを書き溜めていきます

ChapGPT - ChatGPTの始め方、使い方、プログラミングへの利用

初めに

 ChatGPT は、OpenAI が開発した AI チャットサービスです。基本的には、質問したことに回答をしてくれるサービスですが、プログラミングについて質問することで、プログラミングをデバッグしてくれたり、ゼロからプログラミングを書いたりすることもできます。本記事では、ChatGPT の始め方、使い方をまとめます。


ChatGPT

ChatGPT とは

 ChatGPT とは、OpenAI という企業が開発した AI によるチャットサービスです。質問を入力すると、それに対して AI が返答してくれます。

ChatGPT の始め方

openai.com

 上のリンク先にアクセスし、"TRY ChatGPT" をクリックします。

 初回は、Sign up をして、アカウント登録します。アカウントがあれば、Log in をクリックし、ログインします。

 メールアドレスを入力します。Google アカウントや Microsoft アカウントでもよいです。

 メールアドレス入力後、電話番号を入力します。そして、ショートメッセージに送られてきた認証コードを入力します。

 通知がいくつかでてくるので、Next をクリックする。

 この画面までたどりづけば、ok です。

ChatGPT の使い方

 画面下の入力欄にテキストを入力し、送信します。

 返答してくれます。

 画面左側から過去のチャット履歴を選択することができます。チャットの履歴を削除する場合は、ごみ箱をクリックすると、チェックマークが表示されるので、それをクリックします。

 画面左下からダークモードとライトモードの切り替えもできます。


ChatGPT にコードを修正してもらう

 ChatGPT にコードの修正案を生成してもらってみます。

 今回は、四捨五入する関数を修正してもらいます。

 仕様としては、四捨五入したい数字と四捨五入したい桁数を引数にもち、四捨五入された数字を返す関数にします。

(修正前)

//四捨五入する関数
int RoundOff(int num, int digit)
{
    int result;
    if (num % Math.Pow(10, digit) > 5)
    {
        result = num - num % (int)Math.Pow(10, digit);
    }
    else
    {
        result = num - num % (int)Math.Pow(10, digit);
    }

    return result;
}

 不十分な点はいくつかあります。

  • 5 以上ではなく、5 より大きいになっている
  • if の条件式が誤っている
  • result に代入する値も誤っている
  • else 内の処理が if 内の処理と同じである

 もう、なにもかも間違っているとしか思えないぐらい、ミスがあるコードを修正してもらいます。

(修正してもらったコード)

int RoundOff(int num, int digit)
{
    int result;
    if (num % Math.Pow(10, digit) >= Math.Pow(10, digit-1)*5)
    {
        result = (int)(num / Math.Pow(10, digit)) * (int)Math.Pow(10, digit) + (int)Math.Pow(10, digit-1);
    }
    else
    {
        result = (int)(num / Math.Pow(10, digit)) * (int)Math.Pow(10, digit);
    }
    return result;
}

この修正されたコードでは、引数 num を小数点以下 digit 桁で四捨五入します。num を Math.Pow(10, digit) で割った商を計算して、その商に Math.Pow(10, digit) を乗じることで、四捨五入した整数値を計算しています。

また、if 文での判定条件を num % Math.Pow(10, digit) >= Math.Pow(10, digit-1)*5 として、小数点以下 digit 桁目が5以上である場合に四捨五入するようにしています。

以上の修正を行うことで、与えられた引数を正しく四捨五入することができます。

 これは、コメントにもあるとおり、小数点以下の桁に関して四捨五入をする関数になっています。ChatGPT が digit という変数名に反応してそのような仕様にしたのだと考えられます。

 そこで、桁数が1以上の場合の関数に変更するよう修正してもらいました。

(指示)
さきほどのdigitは小数点以下の桁数に関してコードを書かれていましたが、桁数が1以上の場合の四捨五入の関数に修正してください。

(回答)

int RoundOff(int num, int digit)
{
    int result;
    if (digit <= 0)
    {
        return num;
    }
    int divisor = (int)Math.Pow(10, digit-1);
    int remainder = num % divisor;
    int quotient = num / divisor;

    if (remainder >= divisor / 2)
    {
        result = (quotient + 1) * divisor;
    }
    else
    {
        result = quotient * divisor;
    }
    return result;
}

この修正されたコードでは、引数 num の小数点以下の桁数ではなく、整数部分の桁数が digit 桁以上である場合に四捨五入を行います。

具体的には、Math.Pow(10, digit-1) を使って divisor という変数を定義し、num を divisor で割った商を quotient として計算します。そして、num を divisor で割った余りを remainder として計算します。ここで、remainder が divisor / 2 以上である場合には、quotient に1を加えた値に divisor を乗じたものを result とします。それ以外の場合には、quotient に divisor を乗じたものを result とします。

また、digit が0以下の場合には、引数 num をそのまま返すようにしています。

以上の修正を行うことで、与えられた引数を正しく四捨五入することができます。

 完璧に修正してくれました。

ChatGPT を使って、2D ゲームのキャラクターを動かしてみた

 今回は、Unity で 2Dゲームのキャラクターの操作をするためのプログラミングを ChatGPT にさせてみました。

ChatGPT にコードを書いてもらう

 今回は、次のような操作ができることを想定して質問してみます。

  • 動きは Rigidbody2D で制御する
  • 横スクロールアクションのように、左右キーを押したら左右に動く
  • 2段ジャンプまでできる
  • キャラクターが進行方向を向くようにする

(1回目の指示)
Unityで2Dキャラクターを動かすコードを書いて。ただし、Rigidbody2Dを使うこと。

(返答)
 はい、Unityで2Dキャラクターを動かすコードを示します。以下のコードでは、キャラクターを左右に移動させる方法を示しています。このコードはC#で書かれています。

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
    public float moveSpeed = 5f;   // キャラクターの移動速度
    private Rigidbody2D rb;       // Rigidbody2Dコンポーネントの参照

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();   // Rigidbody2Dコンポーネントを取得
    }

    void Update()
    {
        // キー入力を取得
        float moveHorizontal = Input.GetAxis("Horizontal");

        // Rigidbody2Dを使ってキャラクターを移動させる
        Vector2 movement = new Vector2(moveHorizontal, 0f);
        rb.velocity = movement * moveSpeed;
    }
}

このスクリプトでは、まずRigidbody2Dコンポーネントを取得します。次に、Update()関数で入力を受け取り、Rigidbody2Dを使ってキャラクターを移動させます。

注意点として、Rigidbody2Dを使う場合、キャラクターの移動処理はUpdate()関数ではなく、FixedUpdate()関数に記述することが推奨されています。そのため、上記のコードを使用する場合は、Update()関数をFixedUpdate()関数に変更することをお勧めします。

(2回目の指示)
さっきのコードのUpdate()関数をFixedUpdate()関数に変更して。さらに、ジャンプ、2段ジャンプもできるようにコードを変更して。

(返答)
 はい、以下のようにUpdate()関数をFixedUpdate()関数に変更し、ジャンプ、2段ジャンプもできるようにコードを変更した例を示します。

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
    public float moveSpeed = 5f;    // キャラクターの移動速度
    public float jumpForce = 10f;   // ジャンプするときの力
    public int maxJumps = 2;        // ジャンプ可能回数
    private int jumpCount = 0;      // ジャンプ回数のカウント
    private Rigidbody2D rb;         // Rigidbody2Dコンポーネントの参照

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();   // Rigidbody2Dコンポーネントを取得
    }

    void FixedUpdate()
    {
        // キー入力を取得
        float moveHorizontal = Input.GetAxis("Horizontal");

        // Rigidbody2Dを使ってキャラクターを移動させる
        Vector2 movement = new Vector2(moveHorizontal, 0f);
        rb.velocity = movement * moveSpeed;

        // ジャンプ処理
        if (Input.GetButtonDown("Jump") && jumpCount < maxJumps)
        {
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            jumpCount++;
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        // 地面に接触したときにジャンプ回数をリセットする
        if (collision.gameObject.CompareTag("Ground"))
        {
            jumpCount = 0;
        }
    }
}

このスクリプトでは、まずジャンプ回数をカウントするための変数jumpCountを宣言し、maxJumps変数で指定された回数だけジャンプができるようにしています。また、jumpForce変数でジャンプするときに加える力を指定できるようにしています。

FixedUpdate()関数では、まずキー入力を受け取り、Rigidbody2Dを使ってキャラクターを移動させます。次に、ジャンプ処理を行います。ジャンプボタンが押されたときに、ジャンプ回数がmaxJumps以下であれば、Rigidbody2Dにジャンプする力を加えます。さらに、接触したオブジェクトが地面である場合には、ジャンプ回数をリセットして、2段ジャンプができるようにしています。

以上が、FixedUpdate()関数を使用して、キャラクターの移動とジャンプ処理を実装する例です。

(3回目の指示)
上のコードをキャラクターが進行方向を向くように変更して。

(返答)
はい、以下のようにコードを変更して、キャラクターが進行方向を向くようにしました。

using UnityEngine;

public class CharacterMovement : MonoBehaviour
{
    public float moveSpeed = 5f;    // キャラクターの移動速度
    public float jumpForce = 10f;   // ジャンプするときの力
    public int maxJumps = 2;        // ジャンプ可能回数
    private int jumpCount = 0;      // ジャンプ回数のカウント
    private Rigidbody2D rb;         // Rigidbody2Dコンポーネントの参照
    private SpriteRenderer sprite;  // SpriteRendererコンポーネントの参照

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();   // Rigidbody2Dコンポーネントを取得
        sprite = GetComponent<SpriteRenderer>(); // SpriteRendererコンポーネントを取得
    }

    void FixedUpdate()
    {
        // キー入力を取得
        float moveHorizontal = Input.GetAxis("Horizontal");

        // Rigidbody2Dを使ってキャラクターを移動させる
        Vector2 movement = new Vector2(moveHorizontal, 0f);
        rb.velocity = movement * moveSpeed;

        // キャラクターの向きを設定
        if (moveHorizontal > 0)
        {
            sprite.flipX = false;   // 右を向く
        }
        else if (moveHorizontal < 0)
        {
            sprite.flipX = true;    // 左を向く
        }

        // ジャンプ処理
        if (Input.GetButtonDown("Jump") && jumpCount < maxJumps)
        {
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            jumpCount++;
        }
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        // 地面に接触したときにジャンプ回数をリセットする
        if (collision.gameObject.CompareTag("Ground"))
        {
            jumpCount = 0;
        }
    }
}

このスクリプトでは、キャラクターの向きを決定するために、SpriteRendererコンポーネントを取得し、flipXプロパティを使用して、左右反転することで向きを変更します。moveHorizontalが正の場合は、キャラクターが右を向き、負の場合は左を向くように設定しています。

以上が、キャラクターが進行方向を向くようにした、コードの例です。

実装

 Unity でさきほど ChatGPT が作ったコードをキャラクターに付けて動かしてみます。

(キャラクターの準備)
 キャラクターの Sprite を表示させます。

 このキャラクターに先ほどのスクリプト、Rigidbody2D、Collider2D(本記事では Box Collider2D)をつけます。

(床の準備)
 適当な長方形に Collder2D をつけ、タグを "Ground" に変更します。

 Inspector から Square をクリックすることで、四角形を生成します。サイズはキャラクターが動ける程度に変更しておきます。

 床として、判定してもらうために、タグを変更します。"Ground" タグはデフォルトではないので、Add Tag をクリックし、"Ground" タグを作ります。

 "Ground" タグが作られたので、床である長方形のタグを "Ground" に変更します。

youtu.be


 あとは、微調整をすればよいでしょう。

 キャラクターの向きが逆なのは、Sprite の向きが逆だからです。キャラクターの Sprite の Scale の x 成分の符号を変えると ok です。

 横移動については、CharacterMovement スクリプトの moveSpeed を変更して調整します。また、ジャンプや重力については、CharacterMovement スクリプトの jumpForce と Rigidbody2D の Gravity Scale から調整します。

ChatGPT の苦手な部分

 複数のコードを書かせるとコードごとの整合性が取れていないことがあります。また、普通に間違えることもあるので、使用者側もある程度、理解して使う必要はあると感じました。

最後に

  • ChatGPT はプログラミングが苦手な人はもちろん、自分でコードが書ける人でも ChatGPT に書かせてから修正するほうが圧倒的に速くプログラミングを完成させることができる
  • 自分にない発想を出してくれることもあり、非常に便利だと感じた
  • C#以外の言語にも対応している
  • 使わない理由がない