Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Main thread bottleneck

Discussion in 'Editor & General Support' started by startas, Dec 28, 2014.

  1. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    I'm doing a 2D tower defense game. I made some simple enemies, a tower, a track,, got some pictures for testing from google and initialized a scene with medium/high action to see how game is performing and if unity will be ok for my game. There will be much more things later, but main thread is already dying with 50-300ms. My game in high levels will have minimum tens of thousands of enemies on the screen and many bullets flying, each object is running its own little movement script. Is there a way to optimize main thread, maybe multithreading ? Maybe i would be better with some another game engine ? My game is light on graphics, but heavy on cpu. HEre my current project : http://www.filedropper.com/towers
     
  2. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    And another question - is there any performance difference in having 10000 - 50000 game objects(prefabs) running its own little script (what i have right now) vs having one big script that controls all those objects ?
     
  3. Ostwind

    Ostwind

    Joined:
    Mar 22, 2011
    Posts:
    2,804
  4. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Ok, trying to put all enemies movement in one script, made some little memory/cpu improvements. Now there is 2 things using most of game cpu time - "Physics2D.Simulate" and my enemy movement script. I'm using right now "Enemies = GameObject.FindGameObjectsWithTag("Enemy");" to find all excisting enemy objects, but i think this is really not a fast way. I'm targeting my game to deal without lag with at least 10k-50k game objects so one could have fun in later game without slideshow, so maybe i need to use some kind of array / list / something else to contain all enemies, and add them as they spawn, and remove from list and destroy as they die. Maybe someone knows a good articles about arrays/lists ? I'm looking for the fastest one to iterate through all list, to remove from list, and to add to list.
     
  5. Ostwind

    Ostwind

    Joined:
    Mar 22, 2011
    Posts:
    2,804
    all Find x methods are horrible for performance if you call then in Update or any repeating place, I think even the manual says that. You should have own list for enemies which you update on spawn/death. Also with that many objects I hope you have some kind of pooling system for various things.
     
  6. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Yes, i know about Find() methods, and i'm looking for the fastest type of list/array right now. No pooling system for now, but maybe later will have to look into it.
     
  7. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Well, i'm trying to use List from System.Collections.Generic to hold all enemies, but i get weird error - "Array index is out of range". I disabled other things and left just simple movement script from start to the end. Maybe someone can help to figure out what is wrong ? Also, i get this error depending on how fast i make enemies, i.e., if every 0.1 second, then i get this error, when second enemy reaches the end, but if i make enemies every 0.2 seconds, then i dont get this error, and all enemies are destroyed when they reach the end.
    Code (JavaScript):
    1. var enemies : List.<GameObject>;
    2. var enemiesToDestroy : List.<int>;
    3.  
    4. function Start () {
    5.   enemies = new List.<GameObject>();
    6.   enemiesToDestroy = new List.<int>();
    7. }
    8.  
    9. function Update () {
    10.   for(var enemy : GameObject in enemies) {
    11.     /*This line gives out of index error*/
    12.     bloon = enemy.GetComponent(Bloon);
    13.     /*and if commented, then this line gives same error*/
    14.     enemy.transform.position = Vector3.MoveTowards(enemy.transform.position, point.position, bloon.speed * Time.deltaTime);
    15.  
    16.     currentDistance = Vector3.Distance(enemy.transform.position, point.position);
    17.     if(currentDistance < distance) {
    18.       currentPoint++;
    19.       if(currentPoint == lastPointNumber) {
    20.         //End of track reached, adding enemy index to list to destroy later
    21.         enemiesToDestroy.Add(enemies.IndexOf(enemy));
    22.       }
    23.     }
    24.   }
    25. //Destroying all enemies, that reached end of track
    26.   for(var index : int in enemiesToDestroy) {
    27.     Destroy(enemies[index]);
    28.     enemies.RemoveAt(index);
    29.   }
    30. //Clearing list that holds positions of enemies to remove from enemies list and destroy
    31.   enemiesToDestroy.RemoveRange(0, enemiesToDestroy.Count);
    32.   enemiesToDestroy.Clear();
    33. }
    34.  
    35. /*And same empty game object has another script that creates enemies*/
    36. function Update () {
    37.   next += Time.deltaTime;
    38.   //Every ~0.1 seconds create a new enemy and add it to the list in previous script which is above
    39.   //Here - if 0.1, then i get error in another script, but if 0.2 or more, then i dont get that error
    40.   if(next >= 0.1) {
    41.     enemy = Instantiate(prefabs[7], Vector3(-8, 3.8, 0), Quaternion.identity);
    42.     gameObject.GetComponent(BloonMovement).enemies.Add(enemy);
    43.     next = 0;
    44.   }
    45. }
    46.  
     
    Last edited: Dec 29, 2014
  8. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    When and where do you get that error? Line 31 in your listing looks a little suspect to me...

    In regards to performance, when you're working with a large data set it's worth considering how your CPU will be operating on the data and the best way to store and access the data for that particular type of operation. In CPU time frames it takes ages to fetch something from RAM (a "cache miss"), during which time the CPU isn't executing the next instruction. So where performance is important the idea is to lay out your data to minimise how often the CPU has to read from RAM before executing the next instruction.

    Don't go nuts with that piece of information, by the way. The vast majority of code doesn't need to be optimised, optimisation without full understanding of a system often makes things worse (sometimes in subtle but nasty ways), and optimisation should only be done after evidential testing shows that there is a problem and that the proposed solution will help. So, before you learn to optimize first learn to profile. (And Unity's Profiler is just one tool of many, and not necessarily the best for a given use case, so don't get hung up over not having access to it without Pro.)
     
    Last edited: Dec 28, 2014
  9. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    First i need a working code to do something else, and now i am getting an error. I tried many variants in lines 31/32, but it didnt help, so just left these for now. It looks like some function (maybe destroy) doesnt do its work immediately, but a little bit later, and when my code goes through, it catches empty object. Maybe someone knows which unity/GenericList functions are reliable and do its work immediately, and which functions do its job later/randomly ?
     
    Last edited: Dec 29, 2014
  10. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    What's the error? Errors tell you what line they're on, and you can double-click them to get the line hilighted in your code editor. Also, while the message is sometimes cryptic, the error should tell you what's wrong so you know what to fix.
     
  11. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    omg omg omg... please read before posting, i wrote everything in post #7. Error "Array index is out of range", line 12, or any first line to try to access variable from list enemies. As i said, if spawning enemies fast enough, then unity doesnt do something instantly, and does it later in the middle of my running code, and then my code gets empty variable from list, or try to access empty variable not in the list.
     
    Last edited: Dec 29, 2014
  12. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Ok, so it looks like i solved my problem for now, i made another gameobject variable obj, and destroyed objects when needed in for(var i = 0; i < enemies.Count; i++) loop with "obj = enemies; enemies.RemoveAt(i); Destroy(obj);", that way it works. So if i have Generic List of type <Type>, and if i use Destroy(mylist[index]) and then mylist.RemoveAt(index), it will fail to remove object from list, maybe because after destroy(object), object variable becomes null, and then list fails to remove that object, because of null or type check somewhere in its implementation.
     
  13. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Is function OnCollisionEnter2D reliable ? I mean, is it called only once ? And will it be called in the middle of my any code ? I'm trying to make one script for all bullets movement, and now i also need to group all collisions handling into 1 function/script. Can anyone see what is wrong with my code ?
    Errors that i get : "parameter name: index, argument is out of range" is at the bottom of CollisionEvent.
    "object of type GameObject has been destroyed but you are still trying to access it" in first line in function CollisionEvent, so looks like bloon game object is already destroyed.

    Code (JavaScript):
    1. /* Bullet.js, attached to bullet object */
    2. //controls - general movement script
    3.  
    4. function OnCollisionEnter2D(col : Collision2D) {
    5.   // AddCollision(bullet object, enemy object)
    6.   controls.AddCollision(gameObject, col.gameObject);
    7. }
    8.  
    9.  
    10. /* Movement.js script, attached to empty object */
    11. var collisionObjects : List.<GameObject>;
    12.  
    13. function Update() {
    14. //All the movement code, it is working ok
    15. //During movement, collisions can appear, and it can destroy objects, so it will mess movement code
    16. }
    17.  
    18. // using lateupdate to deal with collisions, because i need a reliable way to do all this stuff
    19. //after all movement code in update, so it will not mess movement code
    20. function LateUpdate() {
    21.   if(collisionObjects.Count % 2.0 != 0) {
    22.     Debug.Log("Error #1"); // Because collisionObjects are like pairs - bullet, enemy, bullet, enemy,......
    23.   }
    24.   var i : int;
    25.   i = collisionObjects.Count;
    26.   if(i > 0) { // If there was any collisions
    27.     while(i > 1) {
    28.       obj3 = collisionObjects[i-2]; // this will be bullet
    29.       obj4 = collisionObjects[i-1]; // this will be bloon
    30.         Debug.Log("bullet = " + obj3); // to check if really bullet
    31.         Debug.Log("bloon = " + obj4); // to check if really bloon
    32.       CollisionEvent(obj3, obj4); // handling collisions
    33.       //removing bloon and bullet from list
    34.       collisionObjects.RemoveAt(i-1);
    35.       collisionObjects.RemoveAt(i-2);
    36.       i -= 2;
    37.     }
    38.   }
    39.   if(collisionObjects.Count != 0) {
    40.     Debug.Log("Error #2 - some objects left");
    41.   }
    42. }
    43.  
    44. function AddCollision(bullet : GameObject, bloon : GameObject) {
    45.   collisionObjects.Add(bullet);
    46.   collisionObjects.Add(bloon);
    47. }
    48.  
    49. //Handling collisions
    50. function CollisionEvent(bullet : GameObject, bloon : GameObject) {
    51.   bloon.GetComponent(Bloon).lives = 0; //second error is here
    52.   /* Some not important code here */
    53.  
    54.    //removing enemy from enemies list and destroying enemy game object
    55.    index = enemies.IndexOf(bloon);
    56.    enemies.RemoveAt(index); // first error is here
    57.    Destroy(bloon);
    58.  
    59.   //removing bullet from bullets list and destroying bullet game object
    60.   index = bullets.IndexOf(bullet);
    61.   bullets.RemoveAt(index); // and first error is here
    62.   Destroy(bullet);
    63. }
    64.  
    Edit :
    I see now, did some tests, and there is many collisions with same objects, i.e. 1 bullet with n bloons, or n bullets with 1 bloon, so need to change something to skip collisions, that cannot happen anymore because bloon or bullet was already destroyed.
     
    Last edited: Dec 29, 2014
  14. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    So, almost made collisions handling in one script, but i get 2 errors, because somehow some enemies are not in the enemies list and some bullets are not the bullets list, so when trying to remove these objects from lists, i get index out of range errors. Also, in one for loop unity doesnt want to remove all items from list... If anyone wants to take a look, current project is http://www.filedropper.com/towers_1 .
     
  15. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    Now now, it's best to be polite to those trying to help. You did not write "everything" in post #7, starting with not having posted the full error message or even the line number from it.

    Index out of bounds usually comes from looking past the end of a collection. Here's a couple of common ways that can happen:
    - Forgetting that indices start at 0, not 1, so the last index in a collection is (length - 1).
    - Removing items from the collection while iterating over it and not adjusting the counter appropriately.


    If that is your actual code (is it?) then I don't think it works. You're setting obj to point at the entire enemies collection, then passing that to Destroy. Perhaps that first statement needs to be...
    Code (csharp):
    1.  
    2. obj = enemies[i];
    3.  
    You've asked about whether some stuff is delayed. The answer is yes. Specifically, Destroy marks things to be removed at the end of the frame. Operations on collections are immediate, though. You're not getting out of bounds errors as a result of something being delayed by Unity. (Are you using threads, though? If so you could be causing delays yourself.)

    My recommendation is to make 100% certain that you're being consistent about putting things into and taking them out of those lists.

    Three common ways to do this:
    1. In the appropriate components, have them add themselves to the lists in Awake() and remove themselves in OnDestroy(). This makes list management transparent to the rest of your code.
    2. Make a "manager" class that handles spawning and destruction for you. Have a SpawnBlah(...) and DestroyBlah(...) method for each list you need to maintain, and have those create/destroy the objects and add/remove them from the list at the same time. Then make sure this is the only way you're spawning those things.
    3. Similar to 2, but instead of a manager it can be a pair of static methods on your Bullet and Enemy classes.
     
  16. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Oh, that was just typing mistake, in my code that part is correct. I'm not using any threads, unless unity is using some kind of its own multithreading. And i'm instantiating bullets and adding them to the list only in one place - in tower script, it finds nearest enemy, then creates bullet and adds it to the list, and i'm destroying the bullet only in one place, that deals with collisions, but somehow somewhere some bullets still dissapear/or dont get added tot the list...
     
  17. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    I made some progress today, decided to move back collision code to bullet script because i made some variables global and now have fast access to it, plus i dont need collision objects list, and all errors disappeared. Also, tried to improve the game by trying to remove the effect of objects pushing each other away on collision, did that by editing bullet object/prefab - by making rigidbody kinematic, checking istrigger in collider2d, and then implementing ontriggerenter2d function. Also, that improved performance by a bit. For now, i'm thinking about 3 things, maybe someone can help :

    1) Physics2d calculations are still taking a lot of cpu in the late game (fps drops to 15 fps and lower when game is in action) - Physics2D.FixedUpdate is taking 60%-80% of total, half of which is taking Physics2D.Simulate and the other half by Physics2D.ContactReportTriggers. Maybe there is another, faster way to make simple 2d collisions ? Maybe it would be possible to implement myself a simple 2d collision detection ? Because all i need is to detect collisions of objects, nothing else.

    2) Right now my game speed is based on time by multiplying variables by Time.deltaTime. If the game starts lagging really bad, then many things will just start teleporting, so i'm thinking about making game speed based on frames and then making max fps 60 or 30. To remove time dependency and move to frame dependency, is it enough to just remove multiplication by Time.deltaTime ?

    3) Question about 2D graphics : what kind of pictures should i use for 2d game to have good quality/performance ? Does it matter much for performance ? What kind of settings should i change for picture inside unity ?
     
  18. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,500
    1.
    With regards to the physics slowdown, how many physics objects do you have?

    Also, how are you using Rigidbodies? I don't know about the 2D physics system, but in the 3D physics system anything that moves should have a Rigidbody. It's counter-intuitive, but basically all of the static objects are stored in a way that's optimized based on the assumption that they won't move. If you move them then that data has to be modified, which is expensive. If you attach a Rigidbody (and mark it as kinematic, no gravity) then it's stored in a way optimized for it to move. So, in short, if it moves then it should have a Rigidbody component.

    It is quite possible that a custom implementation for bullets could be faster than the built in one. It's a fairly specific use case where you can safely make assumptions that the general purpose solver can not. Don't even consider this until you've confirmed that the built-in solver isn't up to your requirements, though.

    2.
    If Time.deltaTime isn't stable enough for you, I'd suggest looking at FixedUpdate and fixedDeltaTime. These run at a fixed rate that is not tied to the frame rate, and which you can control as one of your project's properties.

    3.
    What do you mean by "kind of pictures"? If you're referring to the format of the image file, Unity will convert the data to a platform-specific internal format when you import it. It will not use the image in whatever format you save the file in. So, use something lossless. I use 32bit PNGs, since these use lossless compression and support an alpha channel, covering all necessary bases.

    As for import settings, the best way to get started is to stick your texture on whatever you're going to use it on and tweak the settings until it looks best. Note that since Unity uses different formats for different platforms you might need to set this per-platform.
     
  19. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    1) Now i have enemies with only box collider 2d attached, and bullets with circle collider 2d and rigidbody2d - its minimum amount of components to make collisions/triggers to work. Fps drops to about 10 with cpu taking about 103ms (72ms - physics), game objects in scene ~1500, total objects in scene ~7700.

    2) Time is not good in a situation, when the game fps drops to 20 and lower, then every object will be moving by a large distance, so there will be situations where bullets will just teleport over enemies without collision in one calculation. Fixed update might help, but i also would like to make that slow action effect when fps drops. I tried removing deltaTime and correcting speeds, and looks like it works.

    3) Yes, i mean picture format, and also picture resolution, what kind of impact does it make to quality/performance, especially if there is performance hit for cpu, because gpu is showing over 1000 fps right now, so i have plenty of space left for improvements for gpu, but i dont want to make it any harder for cpu.
     
  20. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    I thought a little bit about objects pool system. Is there any examples ? What i thought is, i would make some more lists just to hold objects, and when user presses start button and level starts, then i instantiate enough prefab objects for one level and put them all in one of temporary lists (only objects in main list are active and executing scripts), then when i need to spawn some objects, i would just take enough objects from temporary list, change its variables how i need, and add it to the main list for action. Would my idea work, would it increase performance versus what i have now - instantiating objects and adding to the main list on spawn timer ?

    Also, how about garbage collector ? can i control how often it turns on ? Maybe i shouldnt destroy my objects immediately after they die, maybe i could just remove them from main list, and then after level ends or just a few times during the level i could run garbage collector, or something like that ? Could it increase cpu performance ?
     
  21. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    You can't control how often the GC runs but you can control how much garbage you generate. The best way to control garbage is to use a pooling technique like the one you describe. Pooling probably won't make the instantiation (much) cheaper, but it will dramatically cut down on GC time.
     
  22. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    On points 1 and 2, you really need to look at your code with a profiler and find out where the slow spots are. That said, here are some things to consider:
    * You do a lot of potentially expensive List operations inside UpdateCode. IndexOf requires an O(n) search. RemoveAt may force an array reallocation and copy routine. Check out Dictionary/HashTable. They may be better for your purposes. Also note that Removing from the end of a list is faster than removing in the middle.
    * Debug.Log can actually be quite slow. Comment them out unless you actively need them to debug your code.
    * You may be able to speed up physics time by using Layers to cut down on the number of collision checks that need to happen.
    * You may eventually need to have a BulletManager class instead of game logic components on each bullet. The overhead of all those LateUpdate calls may just be too much.

    On #3, the texture compression format will not have any impact on CPU speed, only on GPU memory and, a bit, on GPU performance. You basically always want to store your textures as a lossless format and compress them for the actual game.
     
  23. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Yes, i know, i already removed all debug.log from update functions, that was just for some debugging, but it didnt affect performance.
    That code with a lot of expensive operations was just a quick way to make game logic going, right now i'm trying to use a good objects pool system, that would remove/minimize expensive operations with lists and objects instantiation, which should increase physics and scripts performance.
    I'm already using collision detection by layers and using function OnTriggerEnter2D in script.
     
  24. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Ok, so now, while adopting objects pooling system, i thought about such thing : before pooling, i just had a list of active enemies that were moving, so i just did all the moving in one "for" loop. Now, with pooling system, when i.e. there will be 10k objects in total, and 3k of them will be moving, what would be faster - iterating through all of them, checking if active == true, and then do moving, or make each object to run little movement script on its own ? On one side, i will always be iterating through kind of big list, on the other side, no iteration, but much more function calls.

    And another question, is there any faster way to find closest object to some position than just iterating through all active objects, checking for distance with sqrMagnitude and saving the one with shorter distance ?
     
  25. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,613
    Neither - have two lists, one for active enemies and one for inactive enemies, and move enemies between lists when spawning/despawning them.

    The main way to make that faster is to figure out some way by which you don't need to check 'all active objects' - for example, instead of having one list of all active enemies, break your game world up into 'sectors' (e.g. grid squares) and have one list of enemies per grid square. That way, when you search you can just search the current+neighbouring grid squares instead of the entire enemy list.
     
  26. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    So, i made some progress today, now pooling system works, also code is converted to c#. If someone wants to give some ideas about performance improvements, current project is : http://www.filedropper.com/towers

    One notice, is that compiled standalone game runs much better than in editor, because in editor when i play game, i get some kind of micro stuttering, even if i have like one enemy, it doesnt move completely smooth.

    And what i did with enemies is that i have a few pools for different kind of inactive enemies, and one pool for active enemies; when i need to spawn enemy, i just take one from one of inactive pools and add it to active enemies pool, mark enemy as active, and set script variables to what i need; and when active enemy dies reaches the end, i just mark it as inactive and remove from active enemies pool.

    And one question :
    is changing sprite renderer sprite in game script fast ? Because i could change code, where one enemy dies, and spawns one another in its place:
    /*-------------------------------------*/
    obj = PoolingSystem.ps.getPooledEnemy1();
    obj.transform.position = enemy.gameObject.transform.position;
    obj.SetActive(true);
    obj.GetComponent<Bloon>().current = bloonComponent.current;
    PoolingSystem.ps.activeEnemies.Add(obj);

    index = PoolingSystem.ps.activeEnemies.IndexOf(enemy.gameObject);
    PoolingSystem.ps.activeEnemies.RemoveAt(index);
    enemy.gameObject.SetActive(false);
    /*-------------------------------------*/

    to code, where i just change its sprite and adjust some variables:

    /*-------------------------------------*/
    enemy.gameObject.GetComponent<SpriteRenderer>().sprite = anotherSprite;
    enemy.gameObject.GetComponent<EnemyScript>().hp = 111;
    enemy.gameObject.GetComponent<EnemyScript>().speed = 222;
    enemy.gameObject.GetComponent<EnemyScript>().type = 333;
    /*-------------------------------------*/

    Would it be faster ?
     
    Last edited: Jan 2, 2015
  27. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    SetActive can be fairly expensive, so if you can get away without it, then that's probably even better.

    Also, try to avoid redundant property accesses, especially GetComponent calls. For example, the 2nd case should look like:

    Code (csharp):
    1.  
    2. GameObject enemyGO = enemy.gameObject;
    3. enemyGO.GetComponent<SpriteRenderer>().sprite = anotherSprite;
    4. EnemyScript enemyScript = enemyGO.GetComponent<EnemyScript>()
    5. enemyScript.hp = 111;
    6. enemyScript.speed = 222;
    7. enemyScript.type = 333;
    8.  
     
  28. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Ok, i have another question about rotations : i have 2 points, A and B, and i need to rotate my object, so it would be looking from A to B, how can i do that ? I can correct my images rotations if it needs to be at the beginning specifically in vertical/horizontal position.
     
  29. superpig

    superpig

    Drink more water! Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,613
  30. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    What i need is rotation only on Z axis. I tried a few variants with LookAt, but none of them worked, my objects just disappeared.

    Things like bullet.transform.LookAt(Vector3.back, enemy.transform.position) works in a way that i still can see my object, but it it rotates around all axis, and i just need to rotate around Z axis.
     
    Last edited: Jan 3, 2015
  31. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Try Quaternion.AngleAxis where the Z is the axis and the angle is something you'll need to calculate using basic trig, but it's basically the angle between the up vector (Y axis?) and the vector from A to B.
     
  32. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Wow, i was really dumb, i could have just adopted my code, which rotates enemy ship on corner :D :

    Vector3 dir = target.transform.position - objectToRotate.transform.position;
    float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    Quaternion q = Quaternion.AngleAxis(angle, Vector3.forward);
    objectToRotate.transform.rotation = Quaternion.RotateTowards(target.transform.rotation, q, 3600);

    I just had to pick a big step, so that the rotation would be be done in one calculation. Of course, this rotation is rotating correct, when my picture is painted from left to right - left is tail, right is head.
     
  33. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Also, a few more things - i was blind and didnt see, that generic list also has method Remove(object), so would it be faster using it instead of "index = mylist.IndexOf(object); mylist.RemoveAt(index)" ? And is InvokeRepeating() function fast ? I'm using it now to update some statistics in GUI, and if i will make repeat time like 0.1 - 0.2 seconds, it shouldnt do impact on performance, right ?
     
  34. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    Calling Remove is probably very slightly faster than calling IndexOf and RemoveAt. Both are pretty slow though if called often on large lists.

    Calling a single function once every 100-200 ms should be close to zero cost.

    As always, do the right thing first then let the profiler be your guide for optimization.
     
  35. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    Well, yes, but profiler itself makes kind of big difference, most of time it causes gpu spikes, also it a little bit uses cpu, so its hard to tell what exactly is going on, but i'm looking at what uses most of cpu and trying to optimize it. By the way, is there any statistics in unity ? Like min, max, average values of various things, like this - http://docs.unity3d.com/Manual/iphone-InternalProfiler.html - is such thing available for pc ? That would be useful. And about lists - well, i have to do something, its a game, i cant just sit and watch at empty screen :) So right now, its between iterating through the list that is only growing larger, checking for active objects and doing moving stuff; and iterating through list, that is kept as small as posible, plus all the removing from list operations. There is alot of operations being done in update(), so i have to find an optimal way to do it. Or, maybe it would be faster to have many smaller lists, and 2 lists for every type of enemy/bullet/other stuff - one list for active objects, one list for inactive objects ? That way sizes of lists should decrease by a good amount, making some removing operations cheaper.
     
  36. MakeCodeNow

    MakeCodeNow

    Joined:
    Feb 14, 2014
    Posts:
    1,246
    The profiler does have some cost, but I wouldn't call it a big difference, and without it you're just flying blind. There are various profilers for PC, like VTune (or Xcode on Mac) but they won't tell you much without the source code to the engine, and even then won't help with profiling your C# code.

    There are many other data structures in the world than linear lists. The more you learn about other data structures (in particular Dictionary) and their pros and cons, the more tools you'll have to optimize. Also, you don't have to have to have data structures be exclusive. It's totally fine to have the same GameObject in multiple data structures as long as you keep it all straight. And, as you said, partitioning the structures into smaller sets will help in all cases.
     
  37. startas

    startas

    Joined:
    Nov 14, 2014
    Posts:
    102
    And why sometimes when enemy moves, when it dies, and spawns new same kind of enemy, if new enemy is same old reseted enemy object got from list, then it moves faster and faster after every respawn. All variables gets reseted and nothing changes, only its moving speed increases with every respawn...

    Edit :
    Nevermind, i forgot to make one remove operation, but that speedup effect was really weird and without any errors.
    Also looking forward to unity 5, read somewhere that it will have newer physx version with improved performance, if true, that should increase performance a lot.
     
    Last edited: Jan 4, 2015