未分類

生成AIプログラミング能力検証【Grok編】

きたたく

以下に、Unityで動作するシンプルな生態系シミュレーションの完全なC#コードとセットアップ手順を示します。このシミュレーションでは、動物(エージェント)が食料を探し、繁殖し、死に、エネルギーを管理する仕組みを実装します。ユニークな要素として、「天候システム」を追加し、雨が降ると食料の生成速度が上がり、嵐が来るとエージェントのエネルギー消費が増える機能を入れました。これにより、シミュレーションに戦略性とダイナミズムが加わります。


Unity C#コード

1. Animal.cs(エージェントのスクリプト)

動物の移動、食事、繁殖、死亡を管理します。UnityのNavMeshAgentを使用して自然な移動を実現します。

csharp

using UnityEngine;
using UnityEngine.AI;

public class Animal : MonoBehaviour
{
    private NavMeshAgent agent;
    private float energy = 100f;
    private float maxEnergy = 100f;
    private float energyConsumptionRate = 0.1f;
    private float reproductionThreshold = 80f;
    private float reproductionCost = 50f;
    private GameManager gameManager;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        gameManager = FindObjectOfType<GameManager>();
        Wander();
    }

    void Update()
    {
        // エネルギー消費(天候による増減を考慮)
        energy -= energyConsumptionRate * gameManager.weatherEnergyMultiplier * Time.deltaTime;
        if (energy <= 0)
        {
            Die();
            return;
        }

        // 食料を探す
        if (!agent.hasPath || agent.remainingDistance < 1f)
        {
            FindFoodOrWander();
        }

        // 繁殖チェック
        if (energy >= reproductionThreshold)
        {
            Reproduce();
        }
    }

    void Wander()
    {
        Vector3 randomPoint = transform.position + Random.insideUnitSphere * 10f;
        randomPoint.y = 0;
        NavMeshHit hit;
        if (NavMesh.SamplePosition(randomPoint, out hit, 10f, NavMesh.AllAreas))
        {
            agent.SetDestination(hit.position);
        }
    }

    void FindFoodOrWander()
    {
        GameObject nearestFood = gameManager.GetNearestFood(transform.position);
        if (nearestFood != null && Vector3.Distance(transform.position, nearestFood.transform.position) < 20f)
        {
            agent.SetDestination(nearestFood.transform.position);
        }
        else
        {
            Wander();
        }
    }

    void Eat(GameObject food)
    {
        energy = Mathf.Min(energy + 50f, maxEnergy);
        gameManager.RemoveFood(food);
        Destroy(food);
    }

    void Reproduce()
    {
        energy -= reproductionCost;
        gameManager.SpawnAnimal(transform.position + Random.insideUnitSphere * 2f);
    }

    void Die()
    {
        gameManager.RemoveAnimal(this);
        Destroy(gameObject);
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Food"))
        {
            Eat(other.gameObject);
        }
    }
}

2. Food.cs(食料のスクリプト)

食料オブジェクトを単純に表現し、特にロジックは必要ありませんが、タグを付けて識別可能にします。

csharp

using UnityEngine;

public class Food : MonoBehaviour
{
    void Start()
    {
        gameObject.tag = "Food"; // Animal.csで識別用
    }
}

3. GameManager.cs(ゲームマネージャーのスクリプト)

全体のシミュレーションを管理し、食料生成、天候システム、UI更新を行います。

csharp

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

public class GameManager : MonoBehaviour
{
    public GameObject animalPrefab;
    public GameObject foodPrefab;
    public Text agentCountText;
    public Text foodCountText;
    public Text weatherText;

    private List<Animal> animals = new List<Animal>();
    private List<GameObject> foods = new List<GameObject>();
    private float fieldSize = 50f;
    private float foodSpawnInterval = 2f;
    private float foodSpawnTimer;
    private float weatherChangeTimer;
    private float weatherDuration = 10f;

    public float weatherEnergyMultiplier = 1f; // 天候によるエネルギー消費倍率
    private string currentWeather = "Normal";

    void Start()
    {
        // 初期エージェントと食料を生成
        for (int i = 0; i < 10; i++)
        {
            SpawnAnimal(GetRandomPosition());
        }
        for (int i = 0; i < 20; i++)
        {
            SpawnFood();
        }
    }

    void Update()
    {
        // 食料の再生成
        foodSpawnTimer += Time.deltaTime;
        if (foodSpawnTimer >= foodSpawnInterval / (currentWeather == "Rain" ? 2f : 1f)) // 雨で生成速度2倍
        {
            SpawnFood();
            foodSpawnTimer = 0f;
        }

        // 天候の更新
        weatherChangeTimer += Time.deltaTime;
        if (weatherChangeTimer >= weatherDuration)
        {
            ChangeWeather();
            weatherChangeTimer = 0f;
        }

        // UI更新
        UpdateUI();

        // 全滅チェック
        if (animals.Count == 0)
        {
            Debug.Log("Simulation Ended: All agents died.");
        }
    }

    public void SpawnAnimal(Vector3 position)
    {
        GameObject animalObj = Instantiate(animalPrefab, position, Quaternion.identity);
        Animal animal = animalObj.GetComponent<Animal>();
        animals.Add(animal);
    }

    public void SpawnFood()
    {
        GameObject foodObj = Instantiate(foodPrefab, GetRandomPosition(), Quaternion.identity);
        foods.Add(foodObj);
    }

    public void RemoveAnimal(Animal animal)
    {
        animals.Remove(animal);
    }

    public void RemoveFood(GameObject food)
    {
        foods.Remove(food);
    }

    public GameObject GetNearestFood(Vector3 position)
    {
        GameObject nearest = null;
        float minDistance = float.MaxValue;
        foreach (GameObject food in foods)
        {
            float distance = Vector3.Distance(position, food.transform.position);
            if (distance < minDistance)
            {
                minDistance = distance;
                nearest = food;
            }
        }
        return nearest;
    }

    Vector3 GetRandomPosition()
    {
        Vector3 pos = new Vector3(Random.Range(-fieldSize, fieldSize), 0, Random.Range(-fieldSize, fieldSize));
        return pos;
    }

    void ChangeWeather()
    {
        int weather = Random.Range(0, 3);
        switch (weather)
        {
            case 0:
                currentWeather = "Normal";
                weatherEnergyMultiplier = 1f;
                break;
            case 1:
                currentWeather = "Rain";
                weatherEnergyMultiplier = 0.8f; // エネルギー消費減少
                break;
            case 2:
                currentWeather = "Storm";
                weatherEnergyMultiplier = 1.5f; // エネルギー消費増加
                break;
        }
        weatherText.text = "Weather: " + currentWeather;
    }

    void UpdateUI()
    {
        agentCountText.text = "Agents: " + animals.Count;
        foodCountText.text = "Food: " + foods.Count;
    }
}

Unityのセットアップ手順

以下の手順でUnityプロジェクトをセットアップしてください。これにより、シミュレーションが正しく動作します。

1. シーンの準備

  1. 新しいUnity 3Dプロジェクトを作成。
  2. *平面(Plane)**をシーンに追加し、スケールを(10, 1, 10)に設定(フィールドサイズ50×50に合わせる)。
  3. NavMeshを設定:
    • 平面を選択し、Staticにチェック。
    • Window > AI > Navigationを開き、BakeタブでNavMeshを生成。

※実際の作業はNavMeshSurfaceコンポーネントをつけてBake

2. プレハブの作成

  1. Animalプレハブ:
    • シーンにCapsuleを追加(エージェントとして使用)。
    • NavMeshAgentコンポーネントを追加。
    • Animal.csスクリプトをアタッチ。
    • プレハブとして保存(Assetsフォルダにドラッグ)。
  2. Foodプレハブ:
    • シーンにSphereを追加(スケール(0.5, 0.5, 0.5))。
    • Sphere Colliderを追加し、Is Triggerを有効化。
    • Food.csスクリプトをアタッチ。
    • プレハブとして保存。

3. ゲームマネージャーのセットアップ

  1. 空のGameObjectを作成し、名前をGameManagerに。
  2. GameManager.csをアタッチ。
  3. インスペクターで以下を設定:
    • Animal Prefab: Animalプレハブを割り当て。
    • Food Prefab: Foodプレハブを割り当て。
    • Agent Count Text, Food Count Text, Weather Text: UIテキストを後で割り当て。

4. UIの設定

  1. Canvasをシーンに追加。
  2. 3つのTextオブジェクトを作成し、GameManagerの対応するフィールドに割り当て。
    • 例: “Agents: 0”, “Food: 0”, “Weather: Normal”。

※TextmeshProに対応していないため、プログラムの修正が必要。Github copilotで修正。

5. タグの設定

  • FoodプレハブにFoodタグを追加(Animal.csのOnTriggerEnterで使用)。

6. 実行

  • シーンを再生すると、10匹のエージェントと20個の食料がランダムに生成され、シミュレーションが開始します。

設計のポイントと要件対応

1. AIの動きが自然か

  • NavMeshAgentを使用し、障害物を避けつつ食料に向かう自然な移動を実現。
  • 食料がない場合はランダムウォークで探索。

2. シミュレーションが破綻しないか

  • エネルギー消費と食料生成のバランスを調整(energyConsumptionRateとfoodSpawnInterval)。
  • 天候システムで変動性を持たせ、全滅や過剰増殖を防ぐ。

3. ゲームが適切に終了するか

  • 全エージェントが死ぬとログで終了を通知。
  • 繁殖コストとエネルギー消費で無限増殖を抑制。

4. コードが明確か

  • オブジェクト指向設計に従い、AnimalとGameManagerで役割を分離。
  • コメントと変数名で意図を明確化。

5. パフォーマンス

  • Listを使用しつつ、頻繁な検索を避けるためGetNearestFoodを最適化。
  • 大量のエージェントでもNavMeshが効率的に動作。

6. ユニークな要素

  • 天候システム: 雨(食料増加)と嵐(エネルギー消費増加)で戦略性とダイナミズムを追加。

このコードと手順で、Unity上で動作する生態系シミュレーションを簡単に実行できます。必要に応じてパラメータ(energyConsumptionRateやfoodSpawnInterval)を調整し、シミュレーションのバランスをカスタマイズしてください!

ABOUT ME
きたたく
きたたく
学習工学博士
自由に生きる人を増やしたい大学教員・経営者。
生成AIで経済的自由を達成するための知識を発信中。
元不登校から飛び級で博士号(工学)を取得した連続起業家。
プログラミングを通じて「U-22 プログラミングコンテスト CSAJ 会長賞」「IoT Challenge Award 総務大臣賞」「人工知能学会研究会 優秀賞」など40件を超える賞を受賞。
スマホアプリ会社を創業(売却)し、プログラミングスクールの会社を創業(20店舗経営)

著書:知識ゼロからのプログラミング学習術(秀和システム) 他多数
記事URLをコピーしました