【ゲーム開発のためのC#入門講座・基礎拡張編】関数を使ってみよう(前編)【#6】

2022-01-092.0_C#基礎拡張編

ここが基礎拡張編の最大の目玉といっても過言ではないでしょう。

基礎学習編の変数と同様、プログラミングには欠かせない機能となります。

非常に大事なポイントなので前編・後編に分けて解説しますね。

関数って?

関数とは、何らかの入力を受けて実行した処理の結果を出力する機能のことです。

また結構ふわっとした表現になってしまいますね。それだけ柔軟で便利な機能ということでもあるので、ひとつずつ確認していきましょう。

関数の構成要素は、

  1. 何らかの入力を受け取ることができる
  2. 定義した処理を実行することができる
  3. 処理結果を返すことができる

に分解することができます。

前編では関数のベース部分にあたる「2.定義した処理を実行することができる」を解説します。

関数で定義した処理を実行してみよう

例えばRPGの戦闘システムで下記のダメージ計算式だったとします。

ダメージ計算式の仕様

(攻撃力 – 相手の防御力) * スキルの攻撃倍率(100%) / 100

今まではずっと下記のコメントで囲んでいる場所に処理を記述してきましたね。

public class Hello{
    public static void Main(){
        // ↓ここに今まではずっと書いてきた
        int playerATK = 10;
        int enemyDEF = 5;
        int skillRate = 100;
        int damage = (playerATK - enemyDEF) * skillRate / 100;
        System.Console.Write("勇者の攻撃:");
        System.Console.WriteLine(damage);
        // ここまで
    }
}
出力エリア

勇者の攻撃:5

関数を使うと、別の場所に新しく処理を定義することができるようになります。

早速試してみましょう。

public class Hello{
    public static void Main(){
        // ↓ここに今まではずっと書いてきた
        CalcDamage();
        // ここまで
    }
    
    // ↓新しく処理を定義
    public static void CalcDamage()
    {
        int playerATK = 10;
        int enemyDEF = 5;
        int skillRate = 100;
        int damage = (playerATK - enemyDEF) * skillRate / 100;
        System.Console.Write("勇者の攻撃:");
        System.Console.WriteLine(damage);
    }
}
出力エリア

勇者の攻撃:5

きちんと同じ処理結果が算出されていますね。

関数の最もシンプルな構文は下記の通りです。

public static void 関数名()
{
    ……処理……
}

関数はこのように、定義した処理に名前をつけることができる機能なのです。

なお、「public」と「static」については現状関数を作るためのおまじないだと思ってください。いずれ解説する予定ですが、今は理解するための情報が不足しているため、きちんと情報を揃えてから解説します。あと「void」については後編で解説予定なので、こちらも現時点ではおまじないだと思ってください。

今までコードを記述してきた箇所を見てみると、定義した関数名の後ろに「()」をつけた命令がありますね。これが「指定の関数で定義された処理を実行しなさい」という命令になっています。

// 関数で定義した処理を実行したい時は、関数名の後ろに「()」をつける
関数名();

コンピュータはこの命令を受けると、

  1. 指定の関数までジャンプして、
  2. 定義された処理を実行し、
  3. またジャンプして元の場所に戻り、
  4. 後続の処理を実行していく

という風に動作します。

これまで見た目通りの順番で実行されていましたが、関数を使っていくとあちこちにジャンプしていくことになります。なので、慣れないうちは処理を追いかけるのが少し大変かもしれません。

ただ、上から順番に処理を実行していくという原理原則は変わらないです。

もし処理の流れがわからなくなってしまうことがあったら、理解できているところからひとつずつ処理を追いかけてみるとよいでしょう。

なお、プログラミングの世界では関数で定義した処理を実行することを「関数を呼び出す」と表現します。

関数には変数と同じようなルールがあります。

  • いくつでも作ることができる
  • 同じ名前の関数は基本的には作れない
  • 任意の場所から何度でも呼び出すことができる

この任意の場所から何度でも呼び出すことができるというのがポイントですね。

関数のメリット

関数を活用すると、実行する条件やタイミングは違うのだけれどやることは同じ、といった処理をひとまとめにすることができます。

まずは関数を使わないバージョンを見てみましょう。

public class Hello{
    public static void Main(){
        string choosedOption = "両方教えて!";
        if (choosedOption == "無料のゲームだけ教えて!")
        {
            System.Console.WriteLine("Unity");
            System.Console.WriteLine("Unreal Engine");
            System.Console.WriteLine("Cocos2d-x");
        }
        else if (choosedOption == "有料のゲームだけ教えて!")
        {
            System.Console.WriteLine("SRPG Studio");
            System.Console.WriteLine("スマイルゲームビルダー");
            System.Console.WriteLine("RPGツクール");
        }
        else 
        {
            // 両方教えて!パターン
            // ↓「無料のゲームだけ教えて!」の時と同じ処理
            System.Console.WriteLine("Unity");
            System.Console.WriteLine("Unreal Engine");
            System.Console.WriteLine("Cocos2d-x");
            // ↓「有料のゲームだけ教えて!」の時と同じ処理
            System.Console.WriteLine("SRPG Studio");
            System.Console.WriteLine("スマイルゲームビルダー");
            System.Console.WriteLine("RPGツクール");
        }
        System.Console.WriteLine("色んなゲーム開発ツールがあるね!");
    }
}

選択肢に応じてゲーム開発ツールを表示するプログラムです。「両方教えて!」を選択した場合、他の選択肢を選んだ時と同じ処理を実行していますね。

これを関数に置き換えると、下記のようになります。

public class Hello{
    public static void Main(){
        string choosedOption = "両方教えて!";
        if (choosedOption == "無料のゲームだけ教えて!")
        {
            DisplayFreeTools();
        }
        else if (choosedOption == "有料のゲームだけ教えて!")
        {
            DisplayNotFreeTools();
        }
        else 
        {
            // 両方教えて!パターン
            DisplayFreeTools();
            DisplayNotFreeTools();
        }
        System.Console.WriteLine("色んなゲーム開発ツールがあるね!");
    }
    
    public static void DisplayFreeTools()
    {
        System.Console.WriteLine("Unity");
        System.Console.WriteLine("Unreal Engine");
        System.Console.WriteLine("Cocos2d-x");
    }
    
    public static void DisplayNotFreeTools()
    {
        System.Console.WriteLine("SRPG Studio");
        System.Console.WriteLine("スマイルゲームビルダー");
        System.Console.WriteLine("RPGツクール");
    }
}

どうでしょうか。重複している処理をひとまとめにしたことですっきりしましたね。また、関数につけた名前のおかげで「どんなことを実行する処理なのか」という意味合いもわかりやすくなったように感じます。

もし仮にゲーム開発ツールを追加したくなったとしても、処理を一箇所にまとめたおかげで修正も一箇所で済みます。

public class Hello{
    public static void Main(){
        string choosedOption = "両方教えて!";
        if (choosedOption == "無料のゲームだけ教えて!")
        {
            DisplayFreeTools();
        }
        else if (choosedOption == "有料のゲームだけ教えて!")
        {
            DisplayNotFreeTools();
        }
        else 
        {
            // 両方教えて!パターン
            DisplayFreeTools();
            DisplayNotFreeTools();
        }
        System.Console.WriteLine("色んなゲーム開発ツールがあるね!");
    }
    
    public static void DisplayFreeTools()
    {
        System.Console.WriteLine("Unity");
        System.Console.WriteLine("Unreal Engine");
        System.Console.WriteLine("Cocos2d-x");
        // ↓ここに追加するだけで対応可能
        System.Console.WriteLine("ティラノスクリプト");
    }
    
    public static void DisplayNotFreeTools()
    {
        System.Console.WriteLine("SRPG Studio");
        System.Console.WriteLine("スマイルゲームビルダー");
        System.Console.WriteLine("RPGツクール");
    }
}
出力エリア

Unity
Unreal Engine
Cocos2d-x
ティラノスクリプト
SRPG Studio
スマイルゲームビルダー
RPGツクール
色んなゲーム開発ツールがあるね!

便利ですね!

なお、関数を定義できるのは下記の場所のみと決まっています。注意してくださいね。

public class Hello{
    // ↓ここから
    
    // ここまで
}

実はずっと使ってた関数「Main」

ところで、この関数の定義、どこかで見覚えがありませんか?

例えば初期設定の下記コードにも、同じように記述されている部分がありますよね。

public class Hello{
    // ↓これってもしや?
    public static void Main(){
        System.Console.WriteLine("Hello C#");
    }
}

そう、この「Main」という名前の処理もまた関数なのです。

これまでずっと活用させていただいているWebサービスは、実行ボタンが押されたらこの「Main」関数を呼び出す、という仕組みになっていたんですね。

ようやく初期設定コードの謎をひとつ解き明かすことができました。

今後も「public」や「static」といった、まだまだよくわからないままになっている部分も理解できるよう解説していきます。少しずつステップアップしていきましょう。

Unityでの活躍ポイント

以前ご紹介した、UnityでC#のプログラムファイルを作成した時に、初期設定として記述されているコードを見てみましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

おまじない「public」と「static」はついていないですが、「Start」も「Update」も関数の定義そのものですよね。

このように、Unity側が用意した関数と、自分自身で定義した独自の関数を組み合わせながらゲームを動かしていく、というのがUnityでのゲーム開発となります。

少しずつUnityの理解に向かって進んでいるのが実感できますね!

実践演習

それでは実際に関数を使ってみましょう。

演習①関数を作ってみよう!

仕様

コメントで囲んである部分を関数「DisplayTotalAmount」に置き換えてください。

テンプレート
public class Hello{
    public static void Main(){
        // ↓ここを関数に切り出して置き換えてみよう!
        int totalAmount = 0;
        totalAmount += 200 * 3;
        totalAmount += 300 * 2;
        totalAmount += 400 * 1;
        System.Console.WriteLine(totalAmount);
        // ここまで
    }
}

演習②関数を何度も呼び出してみよう!

仕様

ループ処理内で関数「CalcDamage」を呼び出してください。

public class Hello{
    public static void Main(){
        for (int i = 0; i < 10; i++) {
            // ↓ここで関数を呼び出そう!
        
            // ここまで
        }
    }
    
    public static void CalcDamage()
    {
        int playerATK = 10;
        int enemyDEF = 5;
        int skillRate = 100;
        int damage = (playerATK - enemyDEF) * skillRate / 100;
        System.Console.Write("勇者の攻撃:");
        System.Console.WriteLine(damage);
    }
}

答え合わせ

演習①の答え

public class Hello{
    public static void Main(){
        // ↓ここを関数に切り出して置き換えてみよう!
        DisplayTotalAmount();
        // ここまで
    }
    
    public static void DisplayTotalAmount()
    {
        int totalAmount = 0;
        totalAmount += 200 * 3;
        totalAmount += 300 * 2;
        totalAmount += 400 * 1;
        System.Console.WriteLine(totalAmount);
    }
}
出力エリア

1600

演習②の答え

public class Hello{
    public static void Main(){
        for (int i = 0; i < 5; i++) {
            // ↓ここで関数を呼び出そう!
        	CalcDamage();
            // ここまで
        }
    }
    
    public static void CalcDamage()
    {
        int playerATK = 10;
        int enemyDEF = 5;
        int skillRate = 100;
        int damage = (playerATK - enemyDEF) * skillRate / 100;
        System.Console.Write("勇者の攻撃:");
        System.Console.WriteLine(damage);
    }
}
出力エリア

勇者の攻撃:5
勇者の攻撃:5
勇者の攻撃:5
勇者の攻撃:5
勇者の攻撃:5

まとめ

  • 関数とは別の場所に新しく処理を定義する機能のこと
  • 定義した一連の処理に名前をつけることができる
  • 任意の場所から何度でも呼び出すことができる

次回はより便利に関数を活用するための「入力」と「出力」について学習していきます。

それでは、今回もお疲れ様でした!

また次の記事でお会いしましょう!

Posted by 夕目紅