Birds and Unity3D, an attempt to optimize
After reading a post about creating birds on Unity3D , I decided to offer my optimization option.
In Unity, it is bad to place a script on each object, especially if there are a lot of them, strong lags appear. In order not to hang the script Boid.cs can be done differently.
Create a class Boid:
In this class, all calculations will be made. To make it independent of game objects, you need to replace the Physics.OverlapSphere function:
This function will be in another class.
Now you can add the calculation function itself:
With this function we get velocity. Now you need to move the bird, for this we add the Update function.
This completes the Boid class.
Now you need to display the birds no matter how.
To do this, I created an array of primitives that I moved on stage. All this was done in the Boids.cs script:
We hang Boids.cs on the camera and launch. At 1,500 birds, I got 70 fps on my computer.
WebPlayer: here
Code: Download
In Unity, it is bad to place a script on each object, especially if there are a lot of them, strong lags appear. In order not to hang the script Boid.cs can be done differently.
Create a class Boid:
public class Boid
{
public Vector3 velocity;
public Vector3 position;//Добавляем положение птицы в пространстве
private float cohesionRadius = 10;
private float separationDistance = 5;
private Boid[] boids;
private Vector3 cohesion;
private Vector3 separation;
private int separationCount;
private Vector3 alignment;
private float maxSpeed = 15;
public Boid(Vector3 pos)
{
position = pos;
}
}
In this class, all calculations will be made. To make it independent of game objects, you need to replace the Physics.OverlapSphere function:
public static Boid[] boids;
static public Boid[] Sphere(Vector3 position, float radius)
{
List mids = new List();
for (int i = 0; i < boids.Length; i++)
{
if (Vector3.Distance(position, boids[i].position) < radius)
mids.Add(boids[i]);
}
return mids.ToArray();
}
This function will be in another class.
Now you can add the calculation function itself:
public void CalculateVelocity()
{
Vector3 newVelocity = Vector3.zero;
cohesion = Vector3.zero;
separation = Vector3.zero;
separationCount = 0;
alignment = Vector3.zero;
boids = Boids.Sphere(position, cohesionRadius); //Здесь мы заменили функцию Physics.OverlapSphere на свою
foreach (Boid boid in boids)
{
alignment += boid.velocity;//Нам больше не нужно получать компонент объекта
cohesion += boid.position;//Больше не обрашаемся к Transfom
if (boid != this && (position - boid.position).magnitude < separationDistance)
{
separation += (position - boid.position) / (position - boid.position).magnitude;
separationCount++;
}
}
cohesion = cohesion / boids.Length;
cohesion = cohesion - position;
cohesion = Vector3.ClampMagnitude(cohesion, maxSpeed);
if (separationCount > 0)
separation = separation / separationCount;
separation = Vector3.ClampMagnitude(separation, maxSpeed);
alignment = alignment / boids.Length;
alignment = Vector3.ClampMagnitude(alignment, maxSpeed);
newVelocity += cohesion * 0.5f + separation * 15f + alignment * 1.5f;
newVelocity = Vector3.ClampMagnitude(newVelocity, maxSpeed);
velocity = (velocity * 2f + newVelocity) / 3f;//Добавлено для большей гладкости движения
if (position.magnitude > 40)
{
velocity += -position.normalized;
}
}
With this function we get velocity. Now you need to move the bird, for this we add the Update function.
public void Update()
{
position += velocity * Time.deltaTime;
Debug.DrawRay(position, separation, Color.green);//Здесь же мы рисуем лучи для отладки
Debug.DrawRay(position, cohesion, Color.magenta);
Debug.DrawRay(position, alignment, Color.blue);
}
This completes the Boid class.
Now you need to display the birds no matter how.
To do this, I created an array of primitives that I moved on stage. All this was done in the Boids.cs script:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Boids : MonoBehaviour {
GameObject[] boidsObjects;
// Use this for initialization
void Start () {
boidsObjects = new GameObject[1500];//Создаём 1500 птиц
boids = new Boid[boidsObjects.Length];
for (int i = 0; i < boids.Length; i++)
{
GameObject boid = GameObject.CreatePrimitive(PrimitiveType.Cube);//Птицы будут кубами
boid.transform.position = Random.insideUnitSphere * 35f;
Destroy(boid.collider);//Удаляем колайдеры чтобы уменьшить лаги
boidsObjects[i] = boid;
boids[i] = new Boid(boid.transform.position);//Создаём объект Boid
}
StartCoroutine(UpdatePhis());//Функция InvokeRepeating мне не нравится
}
IEnumerator UpdatePhis()
{
while (true)
{
int UpdateCount = 0;
for (int i = 0; i < boids.Length; i++)
{
boids[i].CalculateVelocity();
UpdateCount++;
if (UpdateCount > 100)//Чтобы ещё увеличить fps обрабатываем не всех птиц сразу
{
yield return null;
UpdateCount = 0;
}
}
}
}
// Update is called once per frame
void Update () {
for (int i = 0; i < boids.Length; i++)
{
boids[i].Update();//Двигаем птиц
boidsObjects[i].transform.position = boids[i].position;
}
}
//Здесь я разместил замену OverlapSphere
public static Boid[] boids;
static public Boid[] Sphere(Vector3 position, float radius)
{
List mids = new List();
for (int i = 0; i < boids.Length; i++)
{
if (Vector3.Distance(position, boids[i].position) < radius)
mids.Add(boids[i]);
}
return mids.ToArray();
}
}
We hang Boids.cs on the camera and launch. At 1,500 birds, I got 70 fps on my computer.
WebPlayer: here
Code: Download