Optimización código en Unity

Czhincksx

Tengo problemas de rendimiento con la App que estoy haciendo.

Para empezar no entiendo la diferencia entre los FPS reales que me da el script en pantalla con los que muestran las estadísticas.

A parte de eso el problema está en el hilo principal. Como veis se come 9ms frente a los 0.7 del renderizado. En mi ordenador no hay problema, pero cuando paso la app a la tablet los FPS bajan a 30, 20 e incluso menos.

He abierto el proyecto de ejemplo, ese en 3D con lluvia y drones, y teniendo muchísimos más objetos y scripts, el hilo principal se ejecuta en 4ms.

Tampoco he visto una gran diferencia entre la forma en que están programados esos scripts y los míos.

No sé si hay algún truco o algo que deba configurar para mejorar el rendimiento, porque no es para nada normal.

Edit:

Un ejemplo de código en el que al pulsar una flor se tambalea hacia los lados y expulsa unas partículas. Todos son del estilo, no sé si hay algo raro.

using UnityEngine;
using System.Collections;

public class FlowerBehaviourScript : MonoBehaviour {

// Use this for initialization
float max_rotation = 8f;
float rotation_speed = 15f;

bool moving = false;
float rotation;

Transform dust;
 float volume = 0.1f;

void Start () {
	dust = transform.FindChild("FlowerDust");
}

// Update is called once per frame
void Update () {

	if(moving)
		UpdateRotation();
}

void OnMouseDown () {
	moving = true;
	rotation = max_rotation;
	dust.particleSystem.Play();
	this.audio.PlayOneShot(this.audio.clip,volume);

}

void UpdateRotation() {
	Quaternion target = Quaternion.Euler(0, 0, rotation);
	transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * rotation_speed);

	if(Mathf.Abs(target.z) <= Mathf.Abs(transform.rotation.z) + 0.015f){
		rotation *= -0.92f;
	}
	if(Mathf.Abs(rotation) <= 0.05f) {
rotation = 0f;
moving = false;
}
	}
}

1
r2d2rigo

Usas news? Foreach? Tu escena tiene varias capas?

Czhincksx

No sé lo que son news.

No uso Foreach, pero es que tampoco tengo tantos objetos ni scripts.

Mi escena tiene 4 capas, pero en el momento del pantallazo estaban estáticas. Además ahora mismo sólo estamos trabajando en la primera.

1 respuesta
r2d2rigo

#3 Unity no es muy amigo de ir creando objetos cada frame, cuando tiene que liberarlos suele dar parones. Cuelga una foto de la escena en modo overdraw para echarle un vistazo.

Czhincksx

¿A qué te refieres con modo overdraw?

En realidad la escena es muy sencilla en estos momentos. Son 4 plantas y pájaros haciendo animaciones.

He conseguido duplicar los fps eliminando unos poligon colliders que había y cambiándolos por box colliders. Ahora el hilo principal tarda 3.9ms en ejecutarse (en mi PC) y me da entre 45 y 60fps en la tablet. Aun así comparado con AngryBots y sus 5ms da pena, teniendo en cuenta lo que mueve uno y otro.

Potito

Con 29 Drawcalls no vas a ninguna parte, deberias usar 1 o 2.
Las texturas son demasiado grandes.

No es problema de unity, debes optimizar tus assets y la manera de mostrarlos.

Para el ejemplo de la flor en concreto, has probado a usar animaciones en vez de esos complejos calculos?

1 respuesta
Czhincksx

Estoy metiendo todos los sprites que puedo en uno solo de 2048x2048.

Lo que he leído por ahí es que hay gente que testea con gráficas antiguas y hacen 400 o 1000 Drawcalls. Pensé que a este nivel no sería problema hacer 100 ó 200 llamadas.

Las texturas son grandes, pero eso no lo puedo cambiar. Se tienen que ver bien en altas resoluciones.

El caso de la flor sí que podría cambiarlo por una animación. Lo hice así para poder configurarlo con parámetros.

karlozalb

#6 una duda, ¿Eso es aplicable a todo sin importar la envergadura del juego? lo digo porque ahora mismo para Trashman tenemos 8-9, y cuando estaba en GDX con los temas de postprocesado y tal se quedaba en eso más o menos

#9 Oki! Gracias :) la verdad es que estamos haciendo prácticamente todo eso que me comentas, pero el tema de marcar el tick de objeto estático se me había olvidado completamente xD

1 respuesta
Potito

#8 Con 8-9 vas bien, intenta reducirlos con static batching, marcando los objetos estaticos con el flag static, o usando algun asset, no te compliques.

El numero de drawcalls, que sobrecargan la cpu, y el tamaño de las texturas, que ocupan memoria de video, depende del dispositivo al que vaya orientada la aplicacion. Para PC por ejemplo vas sobrado.

Tambien hay q tener en cuenta el numero de Tris.

El secreto, como en todo, esta en el equilibrio.

Intentar no usar meshes complejas, si no primitivas para los colliders, desactivar los objetos q no uses, usar batching, usar atlas, evitar usar instantiate, find, etc...

Czhincksx

Lo que me preocupa respecto a mi aplicación es lo siguiente.

Éste es un ejemplo sacado de aquí: http://www.paladinstudios.com/2012/07/30/4-ways-to-increase-performance-of-your-unity-game/

He creado una escena vacía y el resultado que obtengo es el siguiente:

A parte de la diferencias entre máquinas, no le veo sentido a esos 12ms para una escena vacía.

Leí por ahí que podría tratarse de la VSinc o algo de eso así que desde Project Settings -> Quality lo puse todo al mínimo, incluído VSync Count: Don't Sync.

El caso es que no sé cómo debe estar configurado un proyecto vacío para que vaya lo más rápido posible. Algo falla a la fuerza.

1 respuesta
Potito

#10 Yo creo que lo q necesitas en el Profiler, cogete unos meses de prueba de la version PRO.

La ventana de stats es muy orientativa , lo correcto seria medir los datos en una standalone, ya que unity distorsiona los datos para "eliminar" la influencia de la ventana de scene o del editor.

Si quieres q te de datos mas a tu gusto, ve a EDIT > PROJECT SETTINGS > QUALITY

Ahi marca VSYNC COUNT a DONT SYNC, se te ira de 12.X ms a 0.X y los frames te iran a 2k o 3k

Tambien te variaran los datos dependiendo de la plataforma a la q estes publicando, el ejemplo te lo he puesto para standalone PC/MAC

Te pongo foto de ejemplo para que veas q funciona, algo has hecho mal.

Da igual que la escena este llena o vacia, si cambias el vsync se disparan los frames y baja el main thread

1 1 respuesta
Czhincksx

Nada, no lo entiendo. He reiniciado y todo a ver pero no consigo nada. A pantalla completa emplea unos 12ms (tanto un proyecto nuevo y vacío como mi app), mientras que la demo de AngryBots sólo requiere 8-9ms y unos 7 si desactivo el VSync.

También cambié la plataforma de Android a PC/Mac pero no hay diferencia.

Voy a probar la versión trial de Unity Pro a ver si soluciono algo.

Edit:

¿Puede ser porque esté usando las herramientas de Unity2D?

Edit 2:

Encima es todo muy inconsistente. A veces sin maximizar me marca 3, 4ms y al maximizar sube a 12ms (supongo que por la diferencia de resolución) y otras veces me marca 12ms en ambos casos.

MrPacoPorras

el tamaño de las texturas no afecta a este caso... ya que en realidad solo afecta a la memoria ram. Mientras no explote... De todas formas... segurate de tener bien importadas las texturas.

Con el profiler seguro que sacas algo en claro muy rapido. El principal problema que veo es el numero de triangulos (de vertices en realidad)... si estas usando Unity 2D, intenta regenerar las mallas para que usen menos vertices.

Tampoco es que tengas una salvajada ni mucho menos... me da a mi que va a ser más por algo tipo... tener un monton de rigid vodies por la escena haciendo calculos de fisicas o algo asi.

Como te decian arriba, lo de static batching es imprescindible, pon static a todos los objetos que no se vayan a mover.

Las funciones de 2D no las he mirado demasiado... pero se que esta version ha dado muchos problemas de todo tipo.

Por cierto... fiate más de los FPS del script que de las estadisticas.

Misscelan

Si intentas mover o rotar objectos con colliders, asegúrate que todos tienen rigidbody y están marcados como kinematic.
Si no tienen eso, Physx recalcula todas las colisiones.

Czhincksx

Vale, le he metido el kinematic a todos y creo que ha mejorado levemente.

Estoy marcando como static todos los sprites que no escalo ni roto, pero creo que si no tengo Unity Pro no puedo marcar static batching y no aporta nada.

El trial de unity pro para ver los profiles lo canjearé en cuanto tenga la licencia de desarrollador de Apple y configure el iPhone de mi hermano para probarlo, así le sacaré más partido. A ver si a lo largo de la semana...

Lo que me sigue mosqueando y no logro entender es por qué funciona más rápido la escena del ejemplo que una vacía, y por qué no noto la mejora que se supone que debería notar al desactivar el VSync (en la escena del ejemplo sí que se nota un poco).

Misscelan

Creo que el static batching funciona en la versión gratuita también, el dynamic creo que sólo es para el pro (o a lo mejor es al revés), de todas maneras no hay mucha mejoría si no comparten el mismo material.

En tu escena vacía solo hay una camara sin ningún script adjunto?

1 respuesta
Czhincksx

#16 exacto, sólo una cámara.

Acabo de crear una imagen de 2048x2048 agrupando varios sprites, a ver si se nota en el número de draw calls y en el rendimiento.

kolossdev

Usas Courotines? Ami me a ayudado mucho a bajr los draw calls, quizas te pueda servir de ayuda. Respecto los milisegundos, he hecho lo que dice #11 y funciona, me baja de 11 -12 ms a 0.4.

Czhincksx

Una pregunta un poco tonta...

¿Cuál es el número real de Drawcalls?

¿Sería el valor que aparece en drawcalls, o drawcalls menos el valor de saved by batching?

1 respuesta
MrPacoPorras

#19 Drawcalls a secas... las saved son "extra" que tendría si no hubiese batching

1 1 respuesta
Czhincksx

#20 Ok gracias :)

Usuarios habituales

  • Czhincksx
  • MrPacoPorras
  • kolossdev
  • Misscelan
  • Potito
  • karlozalb
  • r2d2rigo

Tags