Boids
Fishのプレファブを作り、Fishスクリプトを追加する。
- 作者: David M. Bourg,Glenn Seemann,株式会社クイープ
- 出版社/メーカー: オライリージャパン
- 発売日: 2005/01/12
- メディア: 大型本
- 購入: 24人 クリック: 395回
- この商品を含むブログ (78件) を見る
- 作者: 安藤圭吾
- 出版社/メーカー: カットシステム
- 発売日: 2012/04
- メディア: 単行本
- 購入: 1人 クリック: 11回
- この商品を含むブログ (3件) を見る
Boidsを使ったサンプル。
https://dl.dropboxusercontent.com/u/67579260/Unity/Boids/build.html
Main.cs
空のゲームオブジェクトに追加する。
using UnityEngine; using System.Collections; using System.Collections.Generic; public class Main : MonoBehaviour { Boid m_PlayerBoid = null; List<Boid> m_BoidList = null; [SerializeField] BoidForceCalculator m_Calculate = null; void Awake () { m_Calculate = new BoidForceCalculator(); InitFish(); } // Use this for initialization void Start () { } // Update is called once per frame void Update () { Vector3 input = Camera.main.ScreenToWorldPoint(Input.mousePosition); m_PlayerBoid.Position = new Vector3(input.x, 0, input.z); UpdateAI(); } /** * @brief 四面体準備. */ void InitFish() { m_BoidList = new List<Boid>(); for(int i = 0; i < 10; ++i) { GameObject fish = FishFactory.Instance.Create(); Fish script = fish.GetComponent<Fish>(); script.Position = GetRandomPosition(); m_BoidList.Add(script); } m_PlayerBoid = m_BoidList[0]; } Vector3 GetRandomPosition() { float x = Random.Range(-10.0f,10.0f); float z = Random.Range(-10.0f,10.0f); return new Vector3(x, 0.0f, z); } void UpdateAI() { foreach(Boid boid in m_BoidList) { m_Calculate.Apply(boid, m_BoidList); } } }
Boids.cs
using UnityEngine; using System.Collections; /** * @brief Boid. */ public class Boid : MonoBehaviour { /* 速度. */ protected Vector3 m_Velocity = Vector3.zero; public Vector3 Velocity { get { return m_Velocity; } set { m_Velocity = value; } } /* 外力. */ protected Vector3 m_Force = Vector3.zero; public Vector3 Force { get { return m_Force; } set { m_Force = value; } } /* 位置. */ protected Vector3 m_Position = Vector3.zero; public Vector3 Position { get { return m_Position; } set { m_Position = value; } } /* 向き. */ protected Vector3 m_Direction = Vector3.forward; public Vector3 Direction { get { return m_Direction; } set { m_Direction = value; } } /* 摩擦. */ protected float m_Attenuation = 0.9f; }
Fish.cs
魚オブジェクトに追加する。
using UnityEngine; using System.Collections; /** * @brief 魚. */ public class Fish : Boid { void Awake () { } // Use this for initialization void Start () { } // Update is called once per frame void Update () { Vector3 prev = gameObject.transform.position; m_Velocity += m_Force*Time.deltaTime; m_Velocity *= m_Attenuation; m_Position += m_Velocity * Time.deltaTime; gameObject.transform.position = m_Position; Vector3 dir = m_Position - prev; if(dir.magnitude > 0.01f) { m_Direction = dir; gameObject.transform.rotation = Quaternion.LookRotation(m_Direction); } m_Force = Vector3.zero; } }
BoidForceCalculator.cs
魚の挙動を計算する。
using UnityEngine; using System.Collections; using System.Collections.Generic; /** * @brief */ [System.Serializable] public class BoidForceCalculator { [SerializeField] public float SEPARATE_DISTANCE = 1.0f; [SerializeField] public float NEAR_DISTANCE = 10.0f; [SerializeField] public float SCALE = 10.0f; [SerializeField] public float TARGET_DISTANCE = 30.0f; [SerializeField] public float SEPARATE_SCALE = 1.5f; [SerializeField] public float ALIGN_SCALE = 1.0f; [SerializeField] public float COHESION_SCALE = 1.0f; public void Apply(Boid boid, List<Boid> list) { Vector3 force = Vector3.zero; force += SEPARATE_SCALE * CalcSeparation(boid, list); force += ALIGN_SCALE * CalcAlignment(boid, list); force += COHESION_SCALE * CalcCohesion(boid, list); boid.Force = force; } Vector3 CalcSeparation(Boid boid, List<Boid> list) { Vector3 steer = Vector3.zero; int num = 0; float dist = 0.0f; foreach(Boid t in list) { if(t == boid) { continue; } dist = Vector3.Distance(boid.Position, t.Position); if(dist > 0.0f && dist < SEPARATE_DISTANCE) { Vector3 away_dir = Vector3.Normalize(boid.Position - t.Position)/dist; steer += away_dir; ++num; } } if(num > 0) { steer = steer/num; } if(steer.magnitude > 0) { steer.Normalize(); steer *= SCALE; steer = steer - boid.Velocity; } return steer; } Vector3 CalcAlignment(Boid boid, List<Boid> list) { Vector3 sum = Vector3.zero; Vector3 steer = Vector3.zero; int num = 0; float dist = 0.0f; foreach(Boid t in list) { if(t == boid) { continue; } dist = Vector3.Distance(boid.Position, t.Position); if(dist > 0.0f && dist < NEAR_DISTANCE) { sum += t.Velocity; ++num; } } if(num > 0) { sum = sum/(float)num; sum.Normalize(); sum *= SCALE; steer = sum - boid.Velocity; } return steer; } Vector3 CalcCohesion(Boid boid, List<Boid> list) { Vector3 steer = Vector3.zero; Vector3 sum = Vector3.zero; int num = 0; float dist = 0.0f; foreach(Boid t in list) { if(t == boid) { continue; } dist = Vector3.Distance(boid.Position, t.Position); if(dist > 0.0f && dist < NEAR_DISTANCE) { sum += t.Position; ++num; } } if(num > 0) { Boid target = list[0]; dist = Vector3.Distance(target.Position, boid.Position); if(dist < TARGET_DISTANCE) { sum = target.Position; } else { sum = sum/(float)num; } Vector3 dir = Vector3.Normalize(sum - boid.Position); dir = dir * SCALE; steer = dir - boid.Velocity; } return steer; } }
FishFactory.cs
魚を生成する。
using UnityEngine; using System.Collections; /** * @brief 魚ファクトリー. */ public class FishFactory { /* 四面体プレファブ. */ GameObject m_FishPrefab = null; /* インスタンス. */ static FishFactory s_Instance = null; public static FishFactory Instance { get { if(s_Instance == null) { s_Instance = new FishFactory(); } return s_Instance; } } /** * @brief コンストラクタ. */ FishFactory() { m_FishPrefab = Resources.Load("Fish/Fish") as GameObject; } /** * @brief 魚生成. */ public GameObject Create() { GameObject ret = GameObject.Instantiate(m_FishPrefab, Vector3.zero, Quaternion.identity) as GameObject; return ret; } }