Óptimización mediante script.
Ya termine mi proyecto creo que lo subire aquí, queria lanzarlo a steam pero creo que no será el caso(más que todo porque tiene bugs xD), lo que me falta es el level desing.. pero en fin. La DUDA Tengo un spawn de enemigos y se supone que el player tiene que aguantar 5 min pero los enemigos spawnean cada 5 seg. y bueno se van juntando y despues de cierto tiempo me da un bajon de fps(laggg..) y no quiero que pase eso, por si alguien se lo pregunta el player tiene armas.. pero y si el player no quiere disparar? se juntan enemigos y pasa lo del lag, lo que queria es que me den algunas técnicas de óptimización mediante script yo conosco muy poquitas, pienso que para cada juego es diferente la optimización debido a las técnicas de scripting que se utiliza para el juego, así que las tecnicas que más use son:
-RayCast()
-Random.insideUnitySphere
-Physics.overlapSphere();
-7 animaciones para el enemigo
-SystemParticles
-y algunos arboles xD
Así es el juego..
Creo que el problemas puede ser el sistema de particulas?
los desgraciados(enemigos) se curan xD
aparte de que el jugador puede hacer esto
Lo que quiero es óptimzarlo sin quitar nada, pero que sea de un nivel bajo que algunas cosas no me las sé :C
PD: disculpen si es largo pero no sabia como ponerlo xD, la motivación tambien ayuda :)
Si decis que lo vas a subir luego, que mejor que guardar el proyecto en un paquete y subirlo ahora para ver lo del lag, claro si es liviano.
El tema del spam cada 5 segundos lo podes pensar si queres asi: que el juego spawnee un enemigo si el numero total de enemigos es x (meintas mas grande es x mas dificil)
Tenes que ver (y esto es clave en este tipo de juego) como esta constituido un enemigo por si solo. Por ejemplo caso1, tiene un sphereCollider que detecta o no al player y lo ataca y caso 2 calcula la distancia al player, hace raycast, y calcula el angulo, si cumple ataca. El caso uno es mucho mas sencillo de hacer que el caso 2, y si metes mucha cantidad estos scripts(caso2) los fps terminan muertos.
Las optimizaciones primordiales son:
_ Evitar los Updates posibles y componentes innecesarios
_ Poner lo que sea estatico como static
_ Usar occlusion culling
_ Y ser lo mas eficiente posible en los scripts, sobre todo evitar saltos innecesarios, por ejemplo hacer una funcion donde no tiene sentido que haya una, ah pero queda tan bonita.
_ En los sistemas de particulas tenes que limitar la cantidad maxima de particulas y usar un shader acorde, si le metes un standard shader a 10000 particulas estas al horno. Ese humo que tenes ahi podes ratonearlo un poco y agrandar la particula y reducir el numero de rate de emision, a prueba y error.
_ De los Physics el raycast o linecast son los mas baratos siempre que tengan distancias relativamente cortas, el overlap Sphere, Sphere cast, BoxCast etc trata de usarlos si los usar en el Player, un solo elemento, no en cada enemigo.
Cita de: lightbug date=1486605601Si decis que lo vas a subir luego, que mejor que guardar el proyecto en un paquete y subirlo ahora para ver lo del lag, claro si es liviano.
El tema del spam cada 5 segundos lo podes pensar si queres asi: que el juego spawnee un enemigo si el numero total de enemigos es x (meintas mas grande es x mas dificil)
Tenes que ver (y esto es clave en este tipo de juego) como esta constituido un enemigo por si solo. Por ejemplo caso1, tiene un sphereCollider que detecta o no al player y lo ataca y caso 2 calcula la distancia al player, hace raycast, y calcula el angulo, si cumple ataca. El caso uno es mucho mas sencillo de hacer que el caso 2, y si metes mucha cantidad estos scripts(caso2) los fps terminan muertos.
Las optimizaciones primordiales son:
_ Evitar los Updates posibles y componentes innecesarios
_ Poner lo que sea estatico como static
_ Usar occlusion culling
_ Y ser lo mas eficiente posible en los scripts, sobre todo evitar saltos innecesarios, por ejemplo hacer una funcion donde no tiene sentido que haya una, ah pero queda tan bonita.
_ En los sistemas de particulas tenes que limitar la cantidad maxima de particulas y usar un shader acorde, si le metes un standard shader a 10000 particulas estas al horno. Ese humo que tenes ahi podes ratonearlo un poco y agrandar la particula y reducir el numero de rate de emision, a prueba y error.
_ De los Physics el raycast o linecast son los mas baratos siempre que tengan distancias relativamente cortas, el overlap Sphere, Sphere cast, BoxCast etc trata de usarlos si los usar en el Player, un solo elemento, no en cada enemigo.
Lo de spawn veo que es mejor como dices, así le puedo aumentar el daño y la velocidad.
La estructura del enemigo consta de 5 scripts,los 2 primeros son eventos y utilzo metodos para llamar a los mismos, el 3ero es el que detecta mediante el overlapsphere y si hay un collider(player) este activa una serie de metodos,4to hacer dano basicamente se lo adjunto a la animacion en animation,5to recibir daño oncollisionenter() si entra la bala..
Lo de los updates solo llaman a un evento siempre y cuando un player este en su rango de visión.
Basicamente la mayoria de cosas las evita el navmeshagent, por ende supongo que a eso te refieres con el static.
occlusion culling no tenia idea, tratare de usarla.
Te refieres a que declare una función y no la llame?xD.
Los SP rondan alrededor de 15-25 rate(todos), todos excepto 1 tienen additive el otro tiene multiple.
Aquí el linecast en el enemy se activa cuando el player entra en el overlapsphere y sí es una distancia corta, el overlapsphere lo uso en cada enemigo.
Tampoco es que tenga una PC potente a de ser por eso, cuando lo testee le daba parones(sin play) cuando activaba el noise del SP, no creo que les pase eso a todas las maquinas Jajaja.., probaré como va en una pc más potente.
Lo subiré una demo jugable la próxima semana aunque quizás con algunos bugs :C pero serán menos, creo que se les dice Pre-Alpha, mola decirlo :D
el 3ero es el que detecta mediante el overlapsphere y si hay un collider(player)...
Aquí el linecast en el enemy se activa cuando el player entra en el overlapsphere y sí es una distancia corta, el overlapsphere lo uso en cada enemigo.
[/quote]
Sabes bien que hace el overlapSphere?, es como si arrancara de un espera infinitesimalmente pequeña y se agrenda en radio ,devuelve un arreglo de Colliders, pensalo como q checkea si algo esta dentro del radio cada cuadro del sistema de fisicas y lo agranda un delta y vuelve a chequear. Esto es util en contados casos pero si lo que queres es simplemente detectar algo que entra o sale usa un trigger.
Basicamente la mayoria de cosas las evita el navmeshagent, por ende supongo que a eso te refieres con el static.
occlusion culling no tenia idea, tratare de usarla.
[/quote]
En tu caso poco van a hacer el OC y el Static Batching porque tenes un escenario pequeño, el 90% de los objetos supongo que son dinamicos. Si tuvieran un mundo case completamente estatico (pensa un openworld) esto te salva la vida. El occlusion culling basicamente lo que no ve la camara no lo renderiza, incluso si esta detras de un objeto (solo para objetos "static")
Te refieres a que declare una función y no la llame?xD.
[/quote]
Jajaj NO! me refiero a por ejemplo esto:
void Start()
{
InicializarScript();
}
void Update()
{
ModificarValores(10);
}
void InicializarScript()
{
a = 23;
b = 55;
}
void ModificarValores(int valor)
{
a += valor;
b += valor;
}
Cuando lo podes hacer asi:
void Start()
{
a = 23;
b = 55;
}
void Update()
{
a += 10;
b += 10;
}
La idea era un multiplayer de 2 vs 2 y los bots como enemigos neutrales el overlap era para que me de el arreglo de los 4 y ***gui al más cercano.. pero aún no sé Networking..
El 90% es statico con lo unico que 'interactuo' y este se mueva es con una instancia que creo.
Cita de: lightbug date=1486611702Jajaj NO! me refiero a por ejemplo esto:
void Start()
{
InicializarScript();
}
void Update()
{
ModificarValores(10);
}
void InicializarScript()
{
a = 23;
b = 55;
}
void ModificarValores(int valor)
{
a += valor;
b += valor;
}
Cuando lo podes hacer asi:
void Start()
{
a = 23;
b = 55;
}
void Update()
{
a += 10;
b += 10;
}
LOL.. me engañaron, en un blog que encontre decia que esa era la forma correcta ya que al ser un metodo carga más 'rapido'.. todo lo que hice esta hecho así ..
Sh*t.. supongo que será para la prox... aunquesea me ahorrare unos bytes xD
La idea era un multiplayer de 2 vs 2 y los bots como enemigos neutrales el overlap era para que me de el arreglo de los 4 y ***gui al más cercano.. pero aún no sé Networking..
[/quote]
Ah esta bien, en ese caso tiene utilidad.
Cita de: ytinU date=1486618271LOL.. me engañaron, en un blog que encontre decia que esa era la forma correcta ya que al ser un metodo carga más 'rapido'.. todo lo que hice esta hecho así ..
Sh*t.. supongo que será para la prox... aunquesea me ahorrare unos bytes xD
En que blog decia eso?
Lo del start no pasa nada, es innecesario nada mas, lo del Update es lo que mas molesta, por lo menos yo lo veo mas del lado de C que tenes que ahorrar lo que mas puedas porque es la idea de los lenguajes de ese tipo, si tiene o no impacto hacerlo asi depende. La razon por la que personalmente hago funciones dentro de una clase o metodos es para el orden o por algun valor de interes devuelto, y cada una tiene mucho contenido, no da para meter todo en el Update. Pero principalmente si tengo algunas publicas o protegidas para que sean accedidas desde afuera.
Ese "key" no te va arruinar la performance, era solo una sugerencia.
Fijate un detalle, nada mas de molesto que soy aveces, tenes algo asi segun veo:
if(Physics.RayCast .... )
{
if(Input.GetButton ...)
}
Si lo pones alreves la condicion se aliviana mas:
if(Input.GetButton ...)
{
if(Physics.RayCast .... )
}
porque el programa va a ver si esta o no apretada una tecla para hacer el raycast, y no va a hacer el raycast y despues se va a enterar que no apretaste la tecla o el boton.
Cita de: lightbug date=1486619140Ese "key" no te va arruinar la performance, era solo una sugerencia.
Fijate un detalle, nada mas de molesto que soy aveces, tenes algo asi segun veo:
if(Physics.RayCast .... )
{
if(Input.GetButton ...)
}
Si lo pones alreves la condicion se aliviana mas:
if(Input.GetButton ...)
{
if(Physics.RayCast .... )
}
porque el programa va a ver si esta o no apretada una tecla para hacer el raycast, y no va a hacer el raycast y despues se va a enterar que no apretaste la tecla o el boton.
Cuando lo dice alguien más tiene sentido.
Sería bueno tener un pool de enemigos para reutilizar los que matas.
Cita de: juanma_teso date=1486641704Sería bueno tener un pool de enemigos para reutilizar los que matas.
Un pool.. no quiero complicarme mucho, además tengo entendido que el punto de spawn tendrá un arrylist que llamará a los enemigos muertos y los spawnean, además del tema de que los enemigos no mueran porque no encuentras las armas..no sé si se me entendio.. al principio el list<enemigo> aumentara su tamaño ya que al principio no puedo matarlos(tengo que ir a donde estan las armas), y luego decirle que cuando muera un enemigo el tamaño se quede 'statico' y luego si no mata a alguien el tamaño siga aumentando, así creo que funciona un pool, pero de todas formas lo intentaré.
Yo te aconsejaría debugar con el profiler para ver qué factor es el que realmente hace caer el framerate. El pool te lo solucionaría si se trata de un problema de memoria, pero quizá el problema sea demasiada geometría en pantalla o ves a saber el qué. Sin profilear un poco, a la hora de optimizar vas a ciegas
Cita de: musaranya date=1486654307Yo te aconsejaría debugar con el profiler para ver qué factor es el que realmente hace caer el framerate. El pool te lo solucionaría si se trata de un problema de memoria, pero quizá el problema sea demasiada geometría en pantalla o ves a saber el qué. Sin profilear un poco, a la hora de optimizar vas a ciegas
Active el Frame debuger, pero no sé como utilizarlo.. active el profile y enabled pero me salen numeros que no sé que significa, lo normal(los numeros de arriba (# of #)) es 130 of 130 cuando activo el sistemadeparticulas salta a 350 of 350 significa que no hay bajada de fps?
Recalcó que mi PC no es muy bunea a de ser eso..
Lee un poco la documentación oficial, no se puede abrir la ventana del profiler y esperar entenderlo todo. En fin, suerte.
Cita de: ytinU date=1486652971
Un pool.. no quiero complicarme mucho, además tengo entendido que el punto de spawn tendrá un arrylist que llamará a los enemigos muertos y los spawnean, además del tema de que los enemigos no mueran porque no encuentras las armas..no sé si se me entendio.. al principio el list<enemigo> aumentara su tamaño ya que al principio no puedo matarlos(tengo que ir a donde estan las armas), y luego decirle que cuando muera un enemigo el tamaño se quede 'statico' y luego si no mata a alguien el tamaño siga aumentando, así creo que funciona un pool, pero de todas formas lo intentaré.
No entendi ni medio lo que dijiste, si los enemigos no tienen que quedarse en el escenario un object pool es genial, y si se tienen que quedar lo podes perrear facil teniendo una pool igual. Mas que nada se usa cuando tenes muchos Instantiate y Destroy a la vez.
Una vez que mueren te conviene quitar o inhabilitar todo script innecesario ya que no sera usado. Sobre todo si seguis calculando distancias y esas cosas.
El profiler te tira la posta, asi de simple, yo tampoco lo manejo muy bien pero lo uso en lo basico, miro el grafico y detecto picos, me fijo en que momento ocurren, otra cosa que miro es el Garbage Collector (GC) por temas de memoria. Y si seguis bajando tenes parte por parte (fisicas, gpu, etc), quizas viendolo separado podes decir "Ah mira la fisicas me provocan la caida de fps aca y aca ..."
Por que mejor no subis algunos scripts?
Cita de: lightbug date=1486669922No entendi ni medio lo que dijiste, si los enemigos no tienen que quedarse en el escenario un object pool es genial, y si se tienen que quedar lo podes perrear facil teniendo una pool igual. Mas que nada se usa cuando tenes muchos Instantiate y Destroy a la vez.
Una vez que mueren te conviene quitar o inhabilitar todo script innecesario ya que no sera usado. Sobre todo si seguis calculando distancias y esas cosas.
El profiler te tira la posta, asi de simple, yo tampoco lo manejo muy bien pero lo uso en lo basico, miro el grafico y detecto picos, me fijo en que momento ocurren, otra cosa que miro es el Garbage Collector (GC) por temas de memoria. Y si seguis bajando tenes parte por parte (fisicas, gpu, etc), quizas viendolo separado podes decir "Ah mira la fisicas me provocan la caida de fps aca y aca ..."
Por que mejor no subis algunos scripts?
A vale.. nunca use un pool, lo vi recien hoy y supuse que haria eso, pero como explicas es un tema de optimizar en vez de llamar a instante y destroy y quitarle todas sus referencias lo mandas al principio.. mañana subire un demo aquí y veras que la mayoria de cosas usan Instantiate y Destroy xD, a de ser por eso.. es algo así
Las cilindros de color verde son las 'armas' y botan esas esferas que son las balas
ahora imagina esto..
Jajajaja.. usan destroy e instantiate incluso las 'armas'.
PD:No encontre los modelos de arma que me gustaran, no me hagan bullying :C
Cita de: ytinU date=1486671700
Las cilindros de color verde son las 'armas' y botan esas esferas que son las balas
ahora imagina esto..
Jajajaja.. usan destroy e instantiate incluso las 'armas'.
PD:No encontre los modelos de arma que me gustaran, no me hagan bullying :C
Jaja las armas estan muy bien, claro exactamente para esos proyectiles se usa el pool, tenes muchos ejemplos y tutoriales en internet.
Yo lo hago algo asi, seteo el num o capacidad de la pool, Creo en start cada gameObject y los meto en una lista (pool) (que sirve para mantener el orden de que objeto se activa o desactiva) entonces la lista tiene obj1, 2 ,3 ... n . Va activando el primero no activado (el 1) y lo pasa al fondo, y asi, cuando un objeto de estos proyectiles colisiona se desactiva, pasa a estar listo para dispararse de nuevo. Lo complicado de esto es ordenarlo, osea pasarlo al ultimo lugar, no encontre como poder hacerlo en una lista lo cual me parecio muy raro, de seguro hay un metodo acorde para hacerlo.
Tus problemas con el frame rate pueden ser por muchos motivos, tienes que utilizar el debuger aunque lo mas posible como dice musaranya es que sea por demasiados objetos en pantallas, danos mas información haz una captura del cuadro de stats para ver que como andas de geometría y de carga de CPU, y haz una captura del profiler seleccionando el momento que mas carga tienes. Asi podremos ayudarte mas.
Con un pool lo que consigues es evitar usar innecesariamente Instantiate y Destroy que creo recordar afectaba bastante al rendimiento por el recolector de basura, básicamente tienes un objeto con una referencia a otros objetos iguales, luego cómo hagas para referenciarlos (array, arraylist...), ajustar la posición de cada objeto (el pool designa la posición donde se activará o es el propio objeto) e incluso qué objetos activas dentro del pool depende de cómo lo programes, pero es muy útil y te servirá mucho, en tu juego ya lo usas en el sistema de partículas y estaría bien que programaras uno tuyo propio para los enemigos y las balas. Suerte!!
Cita de: lightbug date=1486675546Jaja las armas estan muy bien, claro exactamente para esos proyectiles se usa el pool, tenes muchos ejemplos y tutoriales en internet.
Yo lo hago algo asi, seteo el num o capacidad de la pool, Creo en start cada gameObject y los meto en una lista (pool) (que sirve para mantener el orden de que objeto se activa o desactiva) entonces la lista tiene obj1, 2 ,3 ... n . Va activando el primero no activado (el 1) y lo pasa al fondo, y asi, cuando un objeto de estos proyectiles colisiona se desactiva, pasa a estar listo para dispararse de nuevo. Lo complicado de esto es ordenarlo, osea pasarlo al ultimo lugar, no encontre como poder hacerlo en una lista lo cual me parecio muy raro, de seguro hay un metodo acorde para hacerlo.
Lo aplicaré en un proyecto futuro, me a desmotivado que no encuentre los bugs del navmesh y además de las texturas y cuando alguien hace un juego y es novato tiene altas expectativas yo queria buenos gráficos y eso :C.
Cita de: esr date=1486678454Tus problemas con el frame rate pueden ser por muchos motivos, tienes que utilizar el debuger aunque lo mas posible como dice musaranya es que sea por demasiados objetos en pantallas, danos mas información haz una captura del cuadro de stats para ver que como andas de geometría y de carga de CPU, y haz una captura del profiler seleccionando el momento que mas carga tienes. Asi podremos ayudarte mas.
Puse en google stats y pensé que tenia que descargar algo para que me diera el rendimiento xD(es lo primero que me salia y además era de unity), y luego habia un cuadro muy interesante en el editor queponia stats investigaré a fondo para así saber que tengo que mostrarles y no solo 'tantear'.
Cita de: juanma_teso date=1486739940Con un pool lo que consigues es evitar usar innecesariamente Instantiate y Destroy que creo recordar afectaba bastante al rendimiento por el recolector de basura, básicamente tienes un objeto con una referencia a otros objetos iguales, luego cómo hagas para referenciarlos (array, arraylist...), ajustar la posición de cada objeto (el pool designa la posición donde se activará o es el propio objeto) e incluso qué objetos activas dentro del pool depende de cómo lo programes, pero es muy útil y te servirá mucho, en tu juego ya lo usas en el sistema de partículas y estaría bien que programaras uno tuyo propio para los enemigos y las balas. Suerte!!
No utilizo un pool en el SP, los instancio y destruyo xD
Gracias a todos por los consejos, ahora sólo me queda por aprender las técnicas que me dieron, ya subire el proyecto que les mostre, pero no sé porque me da error...subi el .exe :C
Si entendi bien buscas a los 4 jugadores con el overlapSphere?
Si es asi puedes usar un GameObject.FindWithTag o algo similar no recuerdo la funcion exacta