生成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. シーンの準備
- 新しいUnity 3Dプロジェクトを作成。
- *平面(Plane)**をシーンに追加し、スケールを(10, 1, 10)に設定(フィールドサイズ50×50に合わせる)。
- NavMeshを設定:
- 平面を選択し、Staticにチェック。
- Window > AI > Navigationを開き、BakeタブでNavMeshを生成。
※実際の作業はNavMeshSurfaceコンポーネントをつけてBake
2. プレハブの作成
- Animalプレハブ:
- シーンにCapsuleを追加(エージェントとして使用)。
- NavMeshAgentコンポーネントを追加。
- Animal.csスクリプトをアタッチ。
- プレハブとして保存(Assetsフォルダにドラッグ)。
- Foodプレハブ:
- シーンにSphereを追加(スケール(0.5, 0.5, 0.5))。
- Sphere Colliderを追加し、Is Triggerを有効化。
- Food.csスクリプトをアタッチ。
- プレハブとして保存。
3. ゲームマネージャーのセットアップ
- 空のGameObjectを作成し、名前をGameManagerに。
- GameManager.csをアタッチ。
- インスペクターで以下を設定:
- Animal Prefab: Animalプレハブを割り当て。
- Food Prefab: Foodプレハブを割り当て。
- Agent Count Text, Food Count Text, Weather Text: UIテキストを後で割り当て。
4. UIの設定
- Canvasをシーンに追加。
- 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)を調整し、シミュレーションのバランスをカスタマイズしてください!
