Нет, давайте не отходить от задачи в этом вопросе.
Вы перенесите вычисление расстояния между квадратами в код Update().
(r1+r2)^2
.И в моем варианте вместо && используйте &. Посмотрите, как изменится время работы.
Нет, это вы умножте у вас в коде и потом сравните.
Еще раз, высчитывание расстояния между квадратами через их углы - неправильно, когда они разного размера. Это какое-то другое расстояние.
unit1.centerX - unit2.centerX
.просто персонаж кое где проваливается сквозь стену, а с другой стороны упирается в невидимое препятствие перед стеной.
А можно я тогда значение закеширую?
Я понимаю, если бы вы для каждого квадрата какие-то его свойства предподсчитали. Центр там, размер, что угодно.
А так вы часть вычисления для пары объектов вне таймера считаете. Конечно у вас быстрее будет.
Ну да, если квадраты одного размера, то это еще будет работать. А когда один размера 10x10, а другой - 5x5, это уже не работает. Там надо расстояние между (x1+5, y1+5) и (x2+2.5, y2+2.5) считать.
Да и у вас в коде радиусы везде разные считаются. Конечно, если считать неправильно, то у вас быстрее будет.
Вот из кучи таких мелких ошибок и читов и получается, что ваше решение работает быстрее. Правда неправильно.
Вечером напишу свой бенчмарк.
что за collisionDistance у вас там в коде? Там должен быть квадрат суммы радиусов.
Что там за целое число-то? x1-x2 может быть половинчатым.
7 - 5 = 2.5
, всегда из int получаю float при сложении)Радиус вписанной окружности может тоже быть половинчатым. Радиус описанной окружности - (длина квадрата)/sqrt(2).
r=a/2*2
. Теперь можно смело заявить, что алгоритм работает для целых чисел тоже. Впрочем, речь о целых числах никогда не шла.В принципе, можно свести все к целым числам, но тут надо лишние телодвижения сделать, их я в вашем коде не вижу.
Во-вторых, давайте весь код. Непонятно, что вы там сделали.
public class GameObject
{
public float LeftBorder, TopBorder, CenterX, CenterY, RightBorder, BottomBorder, R;
}
public static class CollisionEngine
{
private static readonly (GameObject unit1, GameObject unit2, float collisionDistance, bool collisionFlag)[] Collisions;
static CollisionEngine()
{
var units = new GameObject[1000];
var random = new Random();
for (var i = 0; i < units.Length; i++)
{
var xl = (float)(random.NextDouble() * 1000);
var yl = (float)(random.NextDouble() * 1000);
var r = (float)(random.NextDouble() * 10);
units[i] = new GameObject { LeftBorder = xl, TopBorder = yl, R = r, CenterX = xl + r, CenterY = yl + r, RightBorder = xl + 2 * r, BottomBorder = yl + 2 * r };
}
Collisions = (from unit1 in units from unit2 in units where unit1 != unit2 select (unit1, unit2, (unit1.R + unit2.R) * (unit1.R + unit2.R), false)).ToArray();
}
private static void Update()
{
for (var i = 0; i < Collisions.Length; i++)
{
var (unit1, unit2, collisionDistance, f) = Collisions[i];
// Check collisions here. Comment out needed algorithm.
// Exact quadratic algorithm.
Collisions[i].collisionFlag = unit1.LeftBorder <= unit2.RightBorder && unit2.LeftBorder <= unit1.RightBorder && unit1.TopBorder <= unit2.BottomBorder && unit2.TopBorder <= unit1.BottomBorder;
//Quick round algorithm.
// Collisions[i].collisionFlag = (unit1.centerX - unit2.centerX) * (unit1.centerX - unit2.centerX) + (unit1.centerY - unit2.centerY) * (unit1.centerY - unit2.centerY) <= collisionDistance;
}
}
public static float TestFPS()
{
const int n = 1000;
var s = new Stopwatch();
s.Start();
for (var i = 0; i < n; i++) Update();
s.Stop();
return n / (s.ElapsedMilliseconds / 1000f);
}
}
Но умножения занимают сильно больше 1 такта, как для сложения/вычитания/сравнения.
Плюс, в вашем решении нельзя обойтись только целыми числами. Даже если входные данные целые. Потому что радиусы, да и центры окружностей будут вещественными. Т.е. оно еще на порядки медленнее.
Collisions[i].collisionFlag = unit1.leftBorder <= unit2.rightBorder && unit2.leftBorder <= unit1.rightBorder && unit1.topBorder <= unit2.bottomBorder && unit2.topBorder <= unit1.bottomBorder;
Collisions[i].collisionFlag = (unit1.centerX - unit2.centerX) * (unit1.centerX - unit2.centerX) + (unit1.centerY - unit2.centerY) * (unit1.centerY - unit2.centerY) <= collisionDistance;
.чем оно легче кучи проверок?
точнее, легче одной проверки?
max(x1, x2) <= min(x1 + w1, x2 + w2)
можно увидеть и вызовы функции, и сортировку, и промежуточные сложения, и дерево ветвлений. (x1-x2)^2+(y1-y2)^2<=(r1+r2)^2
занимает всего 8 операций независимо от поворота или размерности пространства, тяжёлые из которых - это вычитания. Шейпер я нпдеюсь стоит для клиентов и какой то контроллер, скорость ограничивать?)
для начала надо туда шейпер поставить, прокси с зарезанием ненужного и какой то контролер точек вифи