|
Общие вопросы вопросы не попадающие ни в один из доступных разделов |
12.01.2011, 22:14
|
#1
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Быстрый поворот/перемещение множества объектов
Здраствуйте! Язык C#. В Unity новичок, до этого использовал Blitz3D.
Есть массив клонированных объектов, пусть будет 5000 кубов:
cube = new GameObject[5000];
Обновляю его в Update()
float tdt=Time.deltaTime;
for(int i=0;i<cube.Length;i++){
cube[i].transform.Translate(transform.forward * tdt*5);
cube[i].transform.Rotate(Vector3.up*tdt*Random.Range(-50, 50));
}
Если не обновлять положение кубов счетчик показывает 100 FPS,
А если обновлять то ~18 FPS. Уж очень большая разница.
Неужели расчет занимает так много времени?
Может нужно как-то по другому их перемещать/вращать?
Последний раз редактировалось pax, 16.01.2011 в 21:34.
|
(Offline)
|
|
12.01.2011, 23:27
|
#2
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
надо получить transform каждого кубика отдельно и самого объекта отдельно в начале работы скрипта (например в Start) а потом работать с ними. Получение transform через свойство скрипта - медленно
|
(Offline)
|
|
13.01.2011, 00:22
|
#3
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Вот так?
GameObject[] cube;
Transform[] cubet;
void Start()
{
cube = new GameObject[5000];
...
cubet = new Transform[5000];
for(int i=0;i<cube.Length;i++){
...
cubet[i]=cube[i].transform;
}
}
void Update()
{
float tdt=Time.deltaTime;
for(int i=0;i<cube.Length;i++){
cubet[i].Translate(transform.forward * tdt*5);
cubet[i].Rotate(Vector3.up*tdt*Random.Range(-50, 50));
}
}
Сделал, но прирост всего 3-5 FPS, это ничтожно мало
Может при перемещении кубика, автоматический рассчитываются коллизии или еще чего, поэтому так тормозит?!
Может как-то еще можно?
Вот тут
http://unity3d.com/support/documenta...imization.html
Пишут про Vector3 массивы, говорят очень быстрые,как их использовать вместе с GameObject? Будет ли прирост?
|
(Offline)
|
|
13.01.2011, 00:48
|
#4
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Вот так:
GameObject[] cube;
Transform[] cubet;
Transform thisTransform;
void Start()
{
cube = new GameObject[5000];
...
cubet = new Transform[5000];
thisTransform = transform;
for(int i=0;i<cube.Length;i++){
...
cubet[i]=cube[i].transform;
}
}
void Update()
{
Vector3 translation= thisTransform.forward * tdt*5;
float tdt=Time.deltaTime;
for(int i=0;i<cube.Length;i++){
cubet[i].Translate(translation);
cubet[i].Rotate(Vector3.up*tdt*Random.Range(-50, 50));
}
}
Если у тебя Pro версия Unity, то посмотри в профайлер, какая операция больше времени жрет. Update или отрисовка.
|
(Offline)
|
|
13.01.2011, 01:04
|
#5
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
А если кубики с коллайдерами, то конечно надо поставить их в режим IsTrigger хотя бы. А если с RigidBody, то в режим IsKinematic.
|
(Offline)
|
|
13.01.2011, 01:18
|
#6
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Нет не Pro а бесплатная.
Все дела в двух строчках:
cubet[i].Translate(tra);
cubet[i].Rotate(0,tdt*Random.Range(-50, 50),0);
Стоит их закомментировать, как FPS возрастает до 200. А пять вызовов опускают производительность до 100 FPS
Полный исходник:
using UnityEngine;
using System.Collections;
public class NScript : MonoBehaviour {
public string HelloWorldString;
GameObject[] cube;
Transform[] cubet;
Transform thisTransform;
public GameObject myPrefab;
int calls;
void Start()
{
HelloWorldString="Текст из Unity3D!";
thisTransform = transform;
cube = new GameObject[5000];
myPrefab=GameObject.CreatePrimitive(PrimitiveType.Cube);
myPrefab.transform.localScale = new Vector3(10,10,10);
cubet = new Transform[5000];
for(int i=0;i<cube.Length;i++){
cube[i] = (GameObject)Instantiate(myPrefab);
cube[i].transform.position = new Vector3(Random.Range(0, 1024),Random.Range(400, 600),Random.Range(0, 11024));
cubet[i]=cube[i].transform;
}
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Escape))Application.Quit();
calls++;
float tdt=Time.deltaTime;
Vector3 tra= thisTransform.forward * tdt*5;
for(int i=0;i<cube.Length;i++){
cubet[i].Translate(tra);
cubet[i].Rotate(0,tdt*Random.Range(-50, 50),0);
}
}
}
|
(Offline)
|
|
13.01.2011, 01:38
|
#7
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Вот тебе две строчки, каждую можешь попробовать после создания префаба:
myPrefab.GetComponent<BoxCollider>().isTrigger = true; DestroyImmediate(myPrefab.GetComponent<BoxCollider>());
Результаты с первой:
Результаты со второй строчкой:
Если несколько по иному рассчитывать поворот, то немного можно прибавить кадров:
void Update() { if (Input.GetKeyDown(KeyCode.Escape)) Application.Quit(); calls++; float tdt = Time.deltaTime; Vector3 tra = thisTransform.forward * tdt * 5; Vector3 up = Vector3.up; for (int i = 0; i < cube.Length; i++) { cubet[i].Translate(tra); cubet[i].rotation *= Quaternion.AngleAxis(tdt * Random.Range(-50, 50), up); //cubet[i].Rotate(0, tdt * Random.Range(-50, 50), 0); } }
Последний раз редактировалось pax, 13.01.2011 в 03:18.
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
13.01.2011, 03:44
|
#8
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Вот еще способ добиться лучшего результата:
private float lastDelta = 0; private bool secondFrame = false;
void Update() { secondFrame = !secondFrame; float newDelta = Time.deltaTime; if (Input.GetKeyDown(KeyCode.Escape)) Application.Quit();
calls++; float tdt = lastDelta + newDelta;
Vector3 tra = thisTransform.forward * tdt * 5; Vector3 up = Vector3.up; if (secondFrame) { for (int i = 0; i < cube.Length/2; i++) { cubet[i].Translate(tra); cubet[i].rotation *= Quaternion.AngleAxis(tdt*Random.Range(-50, 50), up); } } else { for (int i = cube.Length / 2; i < cube.Length; i++) { cubet[i].Translate(tra); cubet[i].rotation *= Quaternion.AngleAxis(tdt * Random.Range(-50, 50), up); } } lastDelta = newDelta; }
|
(Offline)
|
|
13.01.2011, 10:41
|
#9
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
DestroyImmediate(myPrefab.GetComponent<BoxCollider>());
Увеличило FPS до 50ти
myPrefab.GetComponent<BoxCollider>().isTrigger = true;
Хоть true хоть false не влияет.
Наверно для моей системы 50FPS это предел.
|
(Offline)
|
|
13.01.2011, 11:57
|
#10
|
Дэвелопер
Регистрация: 06.04.2009
Адрес: Запорожье
Сообщений: 1,500
Написано 1,011 полезных сообщений (для 4,642 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Когда в блитце такое делал, какой результат был?
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
__________________
|
(Offline)
|
|
Сообщение было полезно следующим пользователям:
|
|
13.01.2011, 13:54
|
#11
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Сообщение от Evgen
Наверно для моей системы 50FPS это предел.
|
Последний вариант не устраивает? У меня показывал 150+ кадров. А результат практически не отличим.
Сообщение от .Squid
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
|
Тут есть вариант считать матрицы вручную и вручную выводить кубики на экран. Можно я думаю еще ускорить этот процесс, но это только в Pro версии Unity.
|
(Offline)
|
|
13.01.2011, 14:35
|
#12
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Сообщение от pax
Последний вариант не устраивает? У меня показывал 150+ кадров. А результат практически не отличим.
Тут есть вариант считать матрицы вручную и вручную выводить кубики на экран. Можно я думаю еще ускорить этот процесс, но это только в Pro версии Unity.
|
Я понял суть вашего последнего варианта. Спасибо ! только я сделал немного по другому "более гибко". Ну и конечно ничего на свете лучше Sin,Cos нету =)
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape)) Application.Quit();
calls++;
rot=rot+2.5f;//Random.Range(-5, 5);
float speed=Time.deltaTime*25;
float deg2rad=rot*0.0174532925f;
for(int i = 0; i<cube.Length; i++){
cubex[i]+=Mathf.Sin(deg2rad)*speed;
cubey[i]+=Mathf.Cos(deg2rad)*speed;
}
int updates=2000;
int block=(updates*calls)%cube.Length;
int end=block+updates;
if(end>cube.Length)end=cube.Length;
for(int i = block; i<end; i++){
cube[i].transform.position = new Vector3(cubex[i],500,cubey[i]);
cube[i].transform.rotation = Quaternion.AngleAxis(rot,Vector3.up);
}
}
Если взять 6000 кубов и за один Update трансформировать 2000 скорость 90FPS.
Отмечу в каждом Update меняются координаты всех 6000 кубов в первом for, но трансформируются (transform.position/rotation) только 2000. За три кадра 6000.
Тему можно еще развить если обновлять только объекты находящиеся близко к камере или находящиеся в поле зрения камеры. Предполагаю, что первое должно быть проще, а по скорости скорее всего будет небольшая разница.
|
(Offline)
|
|
13.01.2011, 14:40
|
#13
|
Unity/C# кодер
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений (для 5,323 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Ну Вам виднее. Только у вас будет неравномерное перемещение, т.к. 2 обновления по 2000 а одно 1000. Следовательно deltaTime для следующей первой группы в 2000 будет меньше в 2 раза.
float deg2rad=rot*0.0174532925f;
это можно так:
float deg2rad=rot*Mathf.Deg2Rad;
а еще можно
int end=block+updates; if(end>cube.Length)end=cube.Length;
заменить на
int end= Mathf.Clamp(block+updates,0,cube.Length);
|
(Offline)
|
|
13.01.2011, 14:53
|
#14
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Сообщение от .Squid
Когда в блитце такое делал, какой результат был?
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
|
Точно не помню но на Blitz около 5000 кубов где-то 40-50FPS и выдавало. Ну Unity то по мощнее будет чем Blitz.
|
(Offline)
|
|
13.01.2011, 15:01
|
#15
|
Разработчик
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений (для 100 пользователей)
|
Ответ: C# Быстрый поворот/перемещение множества объектов
Сообщение от pax
можно так:
float deg2rad=rot*Mathf.Deg2Rad;
int end= Mathf.Clamp(block+updates,0,cube.Length);
|
Да можно. Только у меня уже привычка (оставшаяся от Java) обращаться к классам типа Mathf.бла-бла-бла только в случае крайней необходимости. Скорость выражения типа Mathf. практический не уменьшают, но когда дело касается 5-10тыс. объектов могут отнять десяток FPS. Если я не прав поправьте.
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 14:05.
|