Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Unity > Общие вопросы

Общие вопросы вопросы не попадающие ни в один из доступных разделов

Ответ
 
Опции темы
Старый 12.01.2011, 22:14   #1
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: C# Быстрый поворот/перемещение множества объектов

надо получить transform каждого кубика отдельно и самого объекта отдельно в начале работы скрипта (например в Start) а потом работать с ними. Получение transform через свойство скрипта - медленно
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 00:22   #3
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: C# Быстрый поворот/перемещение множества объектов

А если кубики с коллайдерами, то конечно надо поставить их в режим IsTrigger хотя бы. А если с RigidBody, то в режим IsKinematic.
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 01:18   #6
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 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 0cube.Lengthi++)
        {
            
cubet[i].Translate(tra);
            
cubet[i].rotation *= Quaternion.AngleAxis(tdt Random.Range(-5050), up);
            
//cubet[i].Rotate(0, tdt * Random.Range(-50, 50), 0);
        
}
    } 

Последний раз редактировалось pax, 13.01.2011 в 03:18.
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Evgen (13.01.2011)
Старый 13.01.2011, 03:44   #8
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 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 0cube.Length/2i++)
            {
                
cubet[i].Translate(tra);
                
cubet[i].rotation *= Quaternion.AngleAxis(tdt*Random.Range(-5050), up);
             }
        }
        else
        {
            for (
int i cube.Length 2cube.Lengthi++)
            {
                
cubet[i].Translate(tra);
                
cubet[i].rotation *= Quaternion.AngleAxis(tdt Random.Range(-5050), up);
            }
        }
        
lastDelta newDelta;
    } 
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 10:41   #9
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 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
.Squid
Дэвелопер
 
Аватар для .Squid
 
Регистрация: 06.04.2009
Адрес: Запорожье
Сообщений: 1,500
Написано 1,011 полезных сообщений
(для 4,642 пользователей)
Ответ: C# Быстрый поворот/перемещение множества объектов

Когда в блитце такое делал, какой результат был?
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
__________________

(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
pax (13.01.2011)
Старый 13.01.2011, 13:54   #11
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 03.10.2005
Адрес: Россия, Рязань
Сообщений: 7,568
Написано 3,006 полезных сообщений
(для 5,323 пользователей)
Ответ: C# Быстрый поворот/перемещение множества объектов

Сообщение от Evgen Посмотреть сообщение
Наверно для моей системы 50FPS это предел.
Последний вариант не устраивает? У меня показывал 150+ кадров. А результат практически не отличим.

Сообщение от .Squid Посмотреть сообщение
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
Тут есть вариант считать матрицы вручную и вручную выводить кубики на экран. Можно я думаю еще ускорить этот процесс, но это только в Pro версии Unity.
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 14:35   #12
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 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
pax
Unity/C# кодер
 
Аватар для pax
 
Регистрация: 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 endMathf.Clamp(block+updates,0,cube.Length); 
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 14:53   #14
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений
(для 100 пользователей)
Сообщение Ответ: C# Быстрый поворот/перемещение множества объектов

Сообщение от .Squid Посмотреть сообщение
Когда в блитце такое делал, какой результат был?
Я так подозреваю, что без правильного кода, который время обращения к памяти сводил бы к минимуму, ты вряд ли существенного прироста производительности добьешься.
Точно не помню но на Blitz около 5000 кубов где-то 40-50FPS и выдавало. Ну Unity то по мощнее будет чем Blitz.
(Offline)
 
Ответить с цитированием
Старый 13.01.2011, 15:01   #15
Evgen
Разработчик
 
Аватар для Evgen
 
Регистрация: 12.01.2011
Адрес: Moscow
Сообщений: 419
Написано 68 полезных сообщений
(для 100 пользователей)
Сообщение Ответ: C# Быстрый поворот/перемещение множества объектов

Сообщение от pax Посмотреть сообщение
можно так:
float deg2rad=rot*Mathf.Deg2Rad
int endMathf.Clamp(block+updates,0,cube.Length); 
Да можно. Только у меня уже привычка (оставшаяся от Java) обращаться к классам типа Mathf.бла-бла-бла только в случае крайней необходимости. Скорость выражения типа Mathf. практический не уменьшают, но когда дело касается 5-10тыс. объектов могут отнять десяток FPS. Если я не прав поправьте.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 14:05.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com