-
Notifications
You must be signed in to change notification settings - Fork 2
Flocking Behaviour
zjy edited this page Jul 13, 2016
·
1 revision
Flocking Behaviour
- 每次汇聚到战旗之后一起再运动会很怪,直接给所有单位一个方向让他们flocking运动好了
- 单位的转向根据团队的速度,不然个体的速度参差不齐,转向会很乱
#代码
Boid.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Boid : MonoBehaviour
{
public BoidMgr mgr;
public float delay;
public float maxVelocity = 10.0f;
public float maxVelocityAdd;
void Start()
{
mgr = FindObjectOfType<BoidMgr>();
delay = UnityEngine.Random.Range(.1f, 1.0f);
maxVelocity = 10.0f;
maxVelocityAdd = 0f;
}
public Vector3 velocity;
public Vector3 steering;
public Vector3 cohesion;
public Vector3 speration;
void Update()
{
if ((delay -= Time.deltaTime) > 0) return;
velocity = mgr.dir * 10.0f;
steering = Vector3.zero;
//QuickLastOne(mgr.boids);
flocking(mgr.boids, out cohesion, out speration);
steering += (cohesion + speration);
velocity = truncate(velocity + steering, maxVelocity * (1.0f + maxVelocityAdd));
transform.position += velocity * Time.deltaTime;
if (maxVelocityAdd > 0f) maxVelocityAdd -= (.1f * Time.deltaTime);
}
void OnDrawGizmos()
{
// Draw a yellow sphere at the transform's position
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, 1);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, 3);
}
public int tooclose_neighborCount;
public int tooaway_neighbourCount;
public void flocking(List<Boid> boids, out Vector3 cohesion, out Vector3 speration)
{
cohesion = Vector3.zero;
speration = Vector3.zero;
tooclose_neighborCount = 0;
tooaway_neighbourCount = 0;
foreach (Boid item in boids)
{
///离自己太远的
//self radius + tolerate radius
if (item != this && Vector3.SqrMagnitude(item.transform.position - transform.position) > (3.0f * 3.0f))
{
cohesion += item.transform.position;
tooaway_neighbourCount++;
}
//self radius + neighbour radius
if (item != this && Vector3.SqrMagnitude(item.transform.position - transform.position) < (2.0f * 2.0f))
{
speration += item.transform.position - transform.position;
tooclose_neighborCount++;
}
}
if (tooclose_neighborCount != 0)
{
speration = ((speration / tooclose_neighborCount) * -1.0f).normalized;
}
else
{
speration = Vector3.zero;
}
///全都远离你?
if (tooaway_neighbourCount > 5)
{
maxVelocityAdd = 0.1f;
cohesion = ((cohesion / tooaway_neighbourCount) - transform.position).normalized * (1 + maxVelocityAdd);
}
else
{
cohesion = Vector3.zero;
}
}
#region util
public Vector3 truncate(Vector3 vector, float max)
{
float rate = vector.magnitude / max;
return rate <= 1.0f ? vector : vector.normalized * max;
}
#endregion
}
BoidMgr.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System;
public class BoidMgr : MonoBehaviour
{
public List<Boid> boids;
public Vector3 dir;
void Start()
{
boids = FindObjectsOfType<Boid>().ToList();
dir = Vector3.right;
}
public enum Dir
{
left,
right,
up,
down,
left_up,
left_down,
right_up,
right_down
}
void OnGUI()
{
for (int i = 0; i < 8; i++)
{
if (GUI.Button(new Rect(10 + i * 60, 10, 50, 40), ((Dir)i).ToString()))
{
Dir curDir = (Dir)i;
switch (curDir)
{
case Dir.left: dir = Vector3.left;
break;
case Dir.right: dir = Vector3.right;
break;
case Dir.up: dir = Vector3.up;
break;
case Dir.down: dir = Vector3.down;
break;
case Dir.left_up: dir = (Vector3.left + Vector3.up);
break;
case Dir.left_down: dir = (Vector3.left + Vector3.down);
break;
case Dir.right_up: dir = (Vector3.right + Vector3.up);
break;
case Dir.right_down: dir = (Vector3.right + Vector3.down);
break;
default:
break;
}
}
}
}
}
#参考文献
-
public function computeAlignment(myAgent:Agent):Point { var v:Point = new Point(); var neighborCount = 0; for each (var agent:Agent in agentArray) { if (agent != myAgent) { if (myAgent.distanceFrom(agent) < 300) { v.x += agent.velocity.x; v.y += agent.velocity.y; neighborCount++;
} } } if (neighborCount == 0) return v; v.x /= neighborCount; v.y /= neighborCount; v.normalize(1); return v;}
v.x += agent.x;
v.y += agent.y;
if (neighborCount == 0) return v;
v.x /= neighborCount;
v.y /= neighborCount;
v = new Point(v.x - myAgent.x, v.y - myAgent.y);
v.normalize(1);
return v;
v.x += agent.x - myAgent.x;
v.y += agent.y - myAgent.y;
if (neighborCount == 0) return v;
v.x /= neighborCount;
v.y /= neighborCount;
v.x *= -1;
v.y *= -1;
v.normalize(1);
return v;
#示例工程