I made a fade out effect on a parallax layer and I've done this:
if(currentBackgroundPhase == BackgroundPhase.Night)
{
foreach(SpriteRenderer sprite in GetComponentsInChildren<SpriteRenderer>())
{
if (sprite.name.Contains("Cloud"))
{
sprite.color = new Color(opaqueCloud.r, opaqueCloud.g, opaqueCloud.b, transitionTimeElapsed / TRANSITION_TIME);
}
}
}
The parallax keeps repositioning cloud sprites and this is the only way I can think to do this.
I've looked profiler and didn't see a drop on performance when the if is called.
Is this too expensive / unefficient because the GetComponensInChildren? If so, is there other way to do this?
I looked on profiler's scripts graphic to see if this is too much but didn't notice anything strange.
I can't test on a bad device because I don't have one, and I want this to work on every android device...
The maximum amount of spriterenderers that can be in children is 20 or so.
Well there are some tips that could be helpful to you
Use object pooling if needed as you don't have to destroy and instantiate clouds again and again.
Try Avoiding Foreach loop its not noticeable right now but it does have an impact over for loop.
If a for each loop used for collection or array of object (i.e. array of all elements other than primitive datatype), GC (Garbage Collector) is called to free space of reference variable at the end of a for each loop.
foreach (Gameobject obj in Collection)
{
//Code Do Task
}
Whereas for loop is used to iterate over the elements using an index and so primitive datatype will not affect performance compared to a non-primitive datatype.
for (int i = 0; i < Collection.length; i++){
//Get reference using index i;
//Code Do Task
}
You can try pooling Gameobjects. Just activating deactivating them.
If one cloud is 100% transparent you can deactivate it and reuse somewhere else. If you are moving the clouds it should be possible.
Related
I have a list of game objects, this keeps track of the monsters i have in my game. when the monster is killed, it will be in position 0 of the list. i want to destroy the object in the scene and remove it from the list.
My question is, does the command: list.RemoveAt(0); call the object to get destroyed or does it leave it existing as some sort of memory leak?
I have tried removing the monster, destroying then removing, saving the monster to a var then removing then destroying and all of them cause bugs. If i knew how the command works, i could narrow down the issue to that or something else in my code.
If you make the list a public variable you can see it in the Unity inspector. When you destroy a monster you will see the list change to have the monster set to null. I would remove the monster from the list before destroying. You can call the OnDestroy method on the monster to remove the monster from the list before it gets destroyed. This uses the list's Remove function instead of RemoveAt.
No, removing it from the List won't destroy it. List.Remove() does not destroy GameObjects - it is just your personal list. You would need to call GameObject.Destroy(list[index]); and then you could list.RemoveAt(index); to remove it from your list. However, if we were talking about a list that was NOT GameObjects and it was your own plain Class(), then you don't need to worry about memory allocation because there is a thing called Garbage Collection where .NET will release an object's memory once noone has an active reference to the object anymore.
I had a similar issue just now.
The problem with storing a Unity GameObject in a list is that deletion becomes a two part problem. First you need to delete the GameObject, then the list item.
It becomes tricky if you are trying to do this in a ForEach loop, because deleting an item while in a ForEach loop causes issues as you are changing the conditions of the loop on the fly by deleting one of the collection.
My work around is to use a for next loop and a boolean flag to get the job done.
do
{
for (t = 0; t < BossObjects.Count; t++)
{
StillWorking = false;
if (BossObjects[t].FlaggedForDeletion)
{
Destroy(BossObjects[t].WholeBossBoxGO); // Delete the Gameobject
BossObjects.Remove(BossObjects[t]); // Delete the List item
StillWorking = true; // Flag we need another iteration
break; // Needed because we changed the list count
}
}
}
while (StillWorking);
I'm running a robot simulation in unity where each of the 300 robots runs the same script and I'm using RayCast for communication between robots. Each robot cast 36 Rays in 10 degree increments to cover all 360 degree every 0.02s. This is done using the RaycastCommand so its done in parallel and isn't causing any performance issues. The issue comes when trying to process the RayCast Data.
I need to loop over every result and compare the tags and ID in each robot script as such:
for(int k =0; k< results.Length; k++) // For every result
{
if(results[k].collider !=null) // Check if RayCast collision happened
{
if(results[k].collider.tag == "Robot") // Check that collision is with robot
{
var ID = results[k].collider.GetComponent<RobotControl>().ID; // Get The robot ID
if(!listID.Contains(ID)) // Check that it hasnt comunicated with that robot yet
{
listID.Add(ID);
Debug.DrawRay(origin + (0.55f* Directions[k]), Directions[k] * results[k].distance , new Color(Directions[k].x, Directions[k].y, Directions[k].z, 1));
// Grab important info here
}
}
}
}
The main problem being I cant use IJobParallelFor since I'm accessing the collider and trying to read the tag, and this is the part of the code tanking my performance since everything else is done using Parallel Jobs. The real issue is accessing the components is expensive.
Any Ideas on how to make it more efficient or somehow parallelize it?
Is there a way to access GameObject specific data, like ID, without accessing their components?
In general instead of 36 casts per robot can't you just use a Physics.OverlapSphere would probably already reduce it a lot since an overlap sphere is pretty easy to compute for the physics engine (if(distance < sphereRadius))
Then one thing costing a lot performance in your case is probably that Contains on a List. There you should rather use a HashSet. See Performance List vs HashSet for your 300 objects that would probably be worth it.
Or further to me it sounds like you would want to know which other robots are close to that one ... you could give each robot a SphereCollider on a certain layer so they only collide with each other, make it Triggers and store them in OnTriggerEnter andremove them in OnTriggerExit.
Is there a way to access GameObject specific data, like ID, without accessing their components?
Well, yes, you can access GameObject specific data like e.g. .name. But that ID is clearly not something GameObject specific but in your RobotControl class so, no, there is not really a way around GetComponent.
However, in newer Unity versions the GetComponent isn't that expensive anymore since the references are hashed and serialized on edit time.
Question is do you really need that ID list or would it be enough to simply save the collider/GameObject references and access the specific component only when really needed?
In your specific case here also the Debug.DrawRay is something extremely expensive and you should not do it too often and for possible 300 * 299 times ;)
I have the following method in my code:
private void OnMouseDown()
{
cube.transform.position = new Vector3(0, 1, 0);
}
When clicked on the gameObject, this method is called. It takes long to change the position of the cube (not more than a second, but still long, at least half a second). It does affect the user playing experience.
If I don't change the position of the cube, but for example its material, it is still slow. So I do know that this doesn't have to do with the line in my OnMouseDown() event.
Note however that I do have around 35 imported 3D meshes in my Scene, as well as over 50 primitive game objects. Does this have anything to do with the method being slow? Because when I make an empty Unity project with just 2 gameObjects, the method is fast.
Is it because of my full scene? Any ideas? Thanks!
If someone knows how to speed it up as well, I'd love to know!
EDIT: If I remove all my 3D meshes, the method is fast...
Unless your transfom tree is hundereds of children deep, this should be pretty much instant, its one of the things Unity has been designed to do quickly, so I think this has to do with the meshes you import. The should not have too many verticies, too many materials, and too many objects.
You can try to go through you objects with a 3D editor package (blender?) and combine the chunks into single objects.
If unity lags when you move an object, it may mean it has too many individual transforms to process. If your scene is intense you can gain a lot of performance by 'baknig' it, combining individual objects into larger meshes (those live on the gpu and cost gpu time not cpu time).
It is also possible that one or more of the meshes you imported has too many verts/triangles. If you currently have 10fps you may want to target having lighter meshes, and as few seperate GameObjects as possible (ideally you want the environment to be just a few combined meshes (to enable culling), not thousands of objects)
solution
Try to check if there are heavy materials are used that can slow the procedure. The game becomes slow when the objects are being added in the project and it destroy the overall efficiency of the game . It happens with me when i used too heavy models in the project the overall speed of the game is decreased . I replaced them with lightweight models of truck and issue was resolved .
Context: I'm using Unity3D's IMGUI where OnGUI{} method is being called/update VERY often (few times per frame) to keep GUI content relevant. I need to iterate through Dictionary with data and display said data, but because I also will be making changes to Dictionary content (Add/Remove) I have to iterate through separate List/Array/whatever.
So in other words right now I have:
foreach (string line in new List<string>(this.myDic.Keys))
{
//fill GUI
//edit Dictionary content if needed
}
The problem here is that it allocates short-lived List multiple time per frame, thousands and thousands times per second and insane amount in general, producing GC. What I want is to avoid this allocation by reusing the same List I initialize at the start. However, another issue came up:
tempList.Clear();
foreach (KeyValuePair<string,string> pair in myDic)
{
tempList.Add(pair.key)
}
var j = tempList.Count;
for (int i = 0; i < j; i++)
{
//fill GUI
//edit Dictionary content if needed
}
As you can see now I basically have two loops, both processing same amount of data. Which leads me to the question: is it moot point here trying to optimize the allocation issue here with reusable List? Or may be even if it looks scary the double-loop variant still better solution?
P.S. Yes, I know, best option would be switch from IMGUI but right now I'm kinda limited to it.
First of all, the only object you allocate by calling new List<string>(this.myDic.Keys) (or this.myDic.Keys.ToArray() alternatively) is an array containing references to already existing objects (strings in your case). So, the GC collects only one object when the scope ends.
The size of that object is about equal to objectCount*referenceSize. The reference size depends on the selected platform: 32bit or 64bit.
Speaking formally, you can save some memory traffic by reusing an existing list, but I guess it's not worth it.
Anyway, if you're up to do that, please note that your approach to refilling the list isn't optimal. I suggest you using .AddRange (it internally uses Array.Copy).
tempList.Clear();
tempList.AddRange(myDic.Keys)
foreach (key in tempList) { ... } //replace with 'for' if you also want to avoid allocation of an iterator
Most likely it's a premature optimization, please do some performance benchmark to test if it makes any sense for your application.
I'm developing a 2D overhead shooter game using C# and XNA. I have a class that I'll call "bullet" and need to update many of these instances every fraction of a second.
My first way to do this was to have a generic List of bullets and simply remove and add new bullets as needed. But in doing so the GC kicks in often and my game had some periodic jerky lag. (Alot of code cut out, but just wanted to show a simple snippet)
if (triggerButton)
{
bullets.Add(new bullet());
}
if (bulletDestroyed)
{
bullets.Remove(bullet);
}
My second and current attempt is to have a separate generic Stack of bullets that I push to when I'm done with a bullet, and pop off a bullet when I need a new one if there's anything in the stack. If there's nothing in the stack then I add a new bullet to the list. It seems to cut the jerky lag but then again, sometimes there's still some jerky lag springing up (though I don't know if it's related).
if (triggerButton)
{
if (bulletStack.Count > 0)
{
bullet temp = bulletStack.Pop();
temp.resetPosition();
bullets.Add(temp);
}
else
{
bullets.Add(new bullet());
}
}
if (bulletDestroyed)
{
bulletStack.Push(bullet);
bullets.Remove(bullet);
}
So, I know premature optimization is the root of all evil, but this was very noticeable inefficiency that I could catch early (and this was before even having to worry about enemy bullets filling the screen). So my questions are: Will pushing unused objects to a stack invoke the garbage collection? Will the references by kept alive or are objects still being destroyed? Is there a better way to handle updating many different objects? For instance, am I getting too fancy? Would it be fine to just iterate through the list and find an unused bullet that way?
There are a lot of issues here, and it's tricky to tell.
First off, is bullet a struct or a class? If bullet is a class, any time you construct one, then unroot it (let it go out of scope or set it to null), you're going to be adding something the GC needs to collection.
If you're going to be making many of these, and updating them every frame, you may want to consider using a List<bullet> with bullet being a struct, and the List being pre-allocated (generate it with a size large enough to hold all of your bullets, so it's not being recreated as you call List.Add). This will help dramatically with the GC pressure.
Also, just because I need to rant:
So, I know premature optimization is the root of all evil, but this was very noticeable inefficiency
Never, ever, be afraid to optimize a routine that you know is causing problems. If you're seeing a performance issue (ie: your lags), this is no longer premature optimization. Yes, you don't want to be optimizing every line of code, but you do need to optimize code, especially when you see a real performance issue. Optimizing it as soon as you see it's a problem is much easier than trying to optimize it later, as any design changes required will be much more easily implemented before you've added a lot of other code that uses your bullet class.
You may find the flyweight design pattern useful. There need be only one bullet object, but multiple flyweights may specify different positions and velocities for it. The flyweights can be stored in a preallocated array (say, 100) and flagged as active or not.
That should eliminate garbage-collection completely, and may reduce the space necessary for tracking each bullet's malleable properties.
I will admit that I don't have any experience in this per se, but I would consider using a traditional array. Initialize the array to a size that is more then you need, and would be the theoretical maximum number of bullets, say 100. Then starting at 0 assign the bullets at the beginning of the array, leaving the last element as a null. So if you had four active bullets your array would look like:
0 B
1 B
2 B
3 B
4 null
...
99 null
The benefit is that the array would always be allocated and therefore you are not dealing with the overhead of a more complex data structure. This is actually fairly similar to how strings work, since they are actually char[] with a null terminator.
Might be worth a shot. One downside, you'll have to do some manual manipulation when removing a bullet, probably move everything after that bullet up a slot. But you are just moving pointers at that point, so I don't think it would have a high penalty like allocating memory or a GC.
You are correct in assuming that by keeping the unused Bullets in a Stack prevents them from being Garbage Collected.
As for the cause of the Lag, have you tried any profiling tools? Just to find where the problem is.
Your stack based solution is pretty close to a class I wrote to generically do this sort of resource pooling:
http://codecube.net/2010/01/xna-resource-pool/
You mentioned that this makes the problem mostly go away, but it still crops up here and there. What's happening is that with this stack/queue based method of pooling, the system will reach a point of stability once you are no longer requesting more new objects than the pool can supply. But if the requests go higher than your previous max # of requested items, it will cause you to have to create a new instance to service the request (thus invoking GC from time to time).
One way you can side-step this is to go through and pre-allocate as many instances as you think you might need at the peak. That way, you won't have any new allocations (at least from the pooled objects), and the GC won't be triggered :-)
List actually has a built in capacity to prevent allocation for every add/remove. Once you exceed the capacity, it adds more ( I think I doubles every time ). The problem may be more on remove than add. Add will just drop on at the first open spot which is tracked by size. To remove, the list has to be condensed to fill in the now empty slot. If you are always removing for the front of the list, then every element needs to slide down.
A Stack still uses an array as its internal storage mechanism. So you are still bound by the add/remove properties of an array.
To make the array work, you need to create all the bullets up from with an Active property for each. When you need a new one, filled the Active flag to true and set all of the new bullets properties. Once complete, flip the Active flag false.
If you wanted to try to eliminate the need to iterate the list ( which could be very large depending on what you are going to allow ) for each repaint, you could try to implement a double linked list within the array. When a new bullet is needed, asked the array for the first available free entry. Go to the last active bullet ( a variable ) and add the new bullet array position into its next active bullet property. When it is time to remove it, go to the previous bullet and change its active bullet property to the removed next active.
//I am using public fields for demonstration. You will want to make them properties
public class Bullet {
public bool Active;
public int thisPosition;
public int PrevBullet = -1;
public int NextBullet = -1;
public List<Bullet> list;
public void Activate(Bullet lastBullet) {
this.Active = true;
this.PrevBullet = lastBullet.thisPosition;
list[this.PrevBullet].NextBullet = this.thisPosition;
}
public void Deactivate() {
this.Active = false;
list[PrevBullet].NextBullet = this.NextBullet;
list[NextBullet].PrevBullet= this.PrevBullet;
}
}
That way, you have a prebuilt array with all the needed bullets but the paint only hits the bullets that are active regardless of their position within the array. You just need to maintain a link to the first active bullet to start the paint and the last active bullet to know where list starts anew.
Now you are just worried about the memory to hold the entire list instead of when the GC is going to clean up.