Iterating through Dictionary/List realtime every few ms - c#

So I have a simple code like this:
public void OnGUI
{
if (this.myDict.Count > 0)
{
//blah
foreach (GameObject gameObject in new List<GameObject>(this.myDict.Keys))
{
//keep stuff up to date
}
}
}
onGUI is Unity's default method that updates every frame (really does not matter how often in this case when we iterate at the level of every frame or slightly lower, stop moving goalposts). And I NEED to keep data up-to-date as often, it is realtime list, but at the same time I NEED to be able to modify Dictionary (add/remove). Now, some random people told me that this foreach which allocates (?) new List every time is a massive memory leak and bad, but when asked why and how they weren't able to explain. I did some googling but result were inconclusive, I found some examples marked as "efficient" which used similar approach.
I'm greatly confused - is there a better way? Shall I define List as a global variable and use it as a temporal bin instead of defining local one each time? Would it matter though?

Related

Optimizing GameObject unique ID assigner Unity

Recently I was working on the door system for my multiplayer game, and I had a problem with door ID (that specifies which door to interact with). I wanted to avoid assigning IDs manually, due to my game has a lot of doors, so I have found a solution - instead of unreliable FindObjectsOfType, I have build following scene looper:
void IterateThroughScene(Scene scene)
{
SortedList<string, NetworkedObject> sortedObjects = new SortedList<string, NetworkedObject>();
//List<CrossSceneAudioSyncListener> audioListeners = new List<CrossSceneAudioSyncListener>();
foreach (GameObject sceneRootObject in scene.GetRootGameObjects())
{
foreach (NetworkedObject netObj in sceneRootObject.GetComponentsInChildren<NetworkedObject>())
{
Vector3 position = netObj.transform.position;
string transformHash = position.x.ToString("0.00") + position.y.ToString("0.00") + position.z.ToString("0.00");
transformHash = Hashing.MD5(transformHash);
sortedObjects.Add(transformHash, netObj);
//CrossSceneAudioSyncListener audioListener = netObj.GetComponent<CrossSceneAudioSyncListener>();
//if(audioListener != null) audioListeners.Add(audioListener);
}
}
//CrossSceneAudioSyncInstance.LoadObjects(audioListeners);
Dictionary<ushort, NetworkedObject> preparedObjects = new Dictionary<ushort, NetworkedObject>();
ushort lastId = _ids[scene.name];
foreach (var part in sortedObjects)
{
NetworkedObject preparedObject = part.Value;
preparedObject.GetObjectData().id = lastId;
preparedObjects[lastId] = preparedObject;
lastId++;
}
_ids[scene.name] = lastId;
_registeredObjects[scene.name] = preparedObjects;
}
Here I list step-by-step what this method is doing:
SortedList is instantiated to hold objects
2 foreach's are getting all objects in the scene
here script generates MD5 of position and adds it to SortedList
After that, Dictionary instance is created to hold final data
Next foreach is done, to loop through SortedList and assign NetworkedObject IDs in a reliable way.
This was doing a great job in small/medium scenes, but I started having serious problems with big scenes - I have a good PC & itaration takes 12 seconds, and my game's target are medium PCs.
So, Do you have any idea how can I optimize this algorithm?
As I do not know the internals of FindObjectsOfType it is hard to compare the method to your snippet. You did however mention that order matters, and as FindObjectsOfType is not guaranteed to return objects in any particular order, it would not work for your use case.
To optimize the snippet you would need to prune your search in some way. As you are looking at all root gameObjects, you can mark each root object with the number of doors that it has as children, and keep a counter for each root. That way, once you reach the number needed sent from the children, it can stop searching that root object.
However, as it seems you would just like to assign ordered ids to objects in a scene for referencing, I would advise to use an editor tool to handle the assignment. The code would be near identical but with the advantage of not needing to care about overhead during runtime as it is computed outside of the game. When implementing any editor tool that alters your scene, make sure to mark the scene as dirty to assure Unity will save the changes.

Does GetComponent<>() impact performance

Just as title say does GetComponent() does impact a lot on performance.
I am asking this because I do not like doing it like this:
public class Player : MonoBehaviour
{
PlayerStats playerStats = this.GetComponent<PlayerStats>();
void Update()
{
var something = playerStats.Asd;
}
}
Instead of that i like using it like this:
public class Player : MonoBehaviour
{
void Update()
{
var something = this.GetComponent<PlayerStats>().Asd;
}
}
Reason for that is because i like breaking code in lot of scripts (it is easier for me to later change something if needed and also use one script for multiple objects) and so if i have a lot of scripts i need to see if i have already defined PlayerStats playerStats.... but not only this one but about a lot of them.
So is using second approach going to slow down my game a lot?
It's worth noting that your first script is invalid and won't compile. The correct way to do that is to make it a global variable but cache or initialize the script in the Start or Awake function. These functions run once and are used for initialization.
Something like this:
PlayerStats playerStats;
void Start()
{
playerStats = this.GetComponent<PlayerStats>();
}
To answer your question, the GetComponent function impacting performance is greatly over exaggerated. You read this everywhere on the internet but it depends on how often it is used. If it is used once in a while or just in few scripts then it's totally fine.
If you have hundreds instances of scripts using GetComponent in the Update function then that's when you will start noticing a little bit of performance hit because GetComponent is making call to the native side. So, it depends on how often it is called and how many instances of scripts are making this call each frame.
The main appeal of using the first approach is that you can set those variables to be public, and in turn access them directly from the Unity Editor, allowing you to drag and drop components as you feel like it.
The second instance of your GetComponent function call means that you aren't caching your variables, slowing down your code with potentially unnecessary checks. So my advice would be to stick with the first instance in which your variable is defined in memory and then altered, rather than being allocated memory each time and then altered.
And a side note. You do not need to call this.GetComponent if the script is attached to an object since the script derives from a MonoBehaviour; you can just call GetComponent<type>() and go about your merry day. :)
I don't think it really matters. I just did a check and using for loop that looped 1,000,000 times and found the exact same 0.02 time delay between both frames.
That being said, it would make your code cleaner because Player.Stats.Asd is cleaner than Player.GetComponent<PlayerStats>().Asd. It makes it more obvious what the intent is. I'm sure it is still a micro optimization to store it as a variable with a public PlayerStats Stats { get; set; }, but that's really if you're using it all the time.
You shouldn't use a variable for every Component it has, because if you do that for every script, the memory being used will start to add up.
Also, note that I'm calling it Stats not PlayerStats because Player.PlayerStats is needlessly redundant. The actual type of it should be called PlayerStats yes, to not confuse it with, say, EnemyStats, but when you go to use both, having Player.Stats and Enemy.Stats is cleaner.

c# Should I store a copy of a field for convenience?

I have developed a habit of sometimes doing this particular thing and I'm wondering why am I doing it, is there any advantage?
Heres an example from a Unity3d game..
In my class I want to do various calculations and so forth with a float ThingYposition which is a field stored somewhere in Thing.transform.position.y. Rather than be writing Thing.transform.position.y so many times I just make a copy of the float I want at the beginning of the program.
public GameObject Thing;
private float ThingYposition;
public Start()
{
ThingYposition = Thing.transform.position.y
}
public Update()
{
//Do stuff every frame with ThingYposition
}
So this way means my lines of code will be a little less cluttered but the program will use a little bit more memory as I'm storing that float twice now. But will it be any faster? Does accessing a deeply embedded field like Thing.transform.position.y actually use any more processing power than accessing my float field?
Do you think this is harmless habit or should I stop?
Also please note in this example I dont care if the original changes at all and I dont want to change it.
You already stated you don't care if the original changes, so I'll skip that part. The only advantage I can see is in a multi-threaded environment. You don't have to worry about another thread mucking with Thing, since you have a private copy of ThingYposition.
In terms of efficiency, you're well into micro optimizing here. If you're having a problem, profile it and experiment with alternatives. But I can't imagine this is something you really need to worry about.
Since you don't care whether or not the original position changes and will not change it yourself, then this is probably the best approach for the use-case you described.
The answer to the other part of your question, is it faster to access a local vs a "deeply embedded field" depends on how Thing.transform.position.y is implemented. If it just a member field, then the access times would be essentially the same for a local copy or the "deeply embedded field". If Thing.transform.position.y is calculated on every access then the local copy would be faster.

Best way to modify a variable by a list of objects in C#

I am trying to build an upgrade system for a project in unity with C# and was wondering what might be the best way to modify a variable, by an array of custom objects (size may vary) that have information of how much should the variable be changed.
some ideas pop to mind, but here are my concerns:
The first one is by using a property:
public float SomeStat{
get{
float modStat = 0;
foreach(StatChanger Stat in StatChangers){
modStat += Stat.valueChange;
}
return modStat;
}
}
this will solve my problem very cleanly, but my concern is that when the property is accessed, every frame for example, there will be a performance drop for a larger amount of items in the list
The second one is to call a function that updates the variable and stores it in another variable to be used every frame without a performance drop:
public float someStat = 10;
public float someStatModifed;
void UpdateStat(){
someStatModifed = someStat;
foreach(StatChanger Stat in StatChangers){
someStatModifed += Stat.valueChange;
}
}
this works but I may forget to call it, and it becomes more messy when having more than one Variable that needs Changing.
should I use a combination of those two or is there better ways of doing it?
I can't say what the performance would be, relative to anything else, but you can use LINQ:
someStatModifed += StatChangers.Sum(stat => stat.valueChange);
Also, don't worry too much about optimizing it until there's a problem. Do try to break it, but don't fix it unless it's noticeable even with large data sets.

C#'s `yield return` is creating a lot of garbage for me. Can it be helped?

I'm developing an Xbox 360 game with XNA. I'd really like to use C#'s yield return construct in a couple of places, but it seems to create a lot of garbage. Have a look at this code:
class ComponentPool<T> where T : DrawableGameComponent
{
List<T> preallocatedComponents;
public IEnumerable<T> Components
{
get
{
foreach (T component in this.preallocatedComponents)
{
// Enabled often changes during iteration over Components
// for example, it's not uncommon for bullet components to get
// disabled during collision testing
// sorry I didn't make that clear originally
if (component.Enabled)
{
yield return component;
}
}
}
}
...
I use these component pools everywhere - for bullets, enemies, explosions; anything numerous and transient. I often need to loop over their contents, and I'm only ever interested in components that are active (i.e., Enabled == true), hence the behavior of the Components property.
Currently, I'm seeing as much as ~800K per second of additional garbage when using this technique. Is this avoidable? Is there another way to use yield return?
Edit: I found this question about the broader issue of how to iterate over a resource pool without creating garbage. A lot of commenters were dismissive, apparently not understanding the limitations of the Compact Framework, but this commenter was more sympathetic and suggested creating an iterator pool. That's the solution I'm going to use.
The implementation of iterators by the compiler does indeed use class objects and the use (with foreach, for example) of an iterator implemented with yield return will indeed cause memory to be allocated. In the scheme of things this is rarely a problem because either considerable work is done while iterating or considerably more memory is allocated doing other things while iterating.
In order for the memory allocated by an iterator to become a problem, your application must be data structure intensive and your algorithms must operate on objects without allocating any memory. Think of the Game of Life of something similar. Suddenly it is the iteration itself that overwhelms. And when the iteration allocates memory a tremendous amount of memory can be allocated.
If your application fits this profile (and only if) then the first rule you should follow is:
avoid iterators in inner loops when a simpler iteration concept is available
For example, if you have an array or list like data structure, you are already exposing an indexer property and a count property so clients can simply use a for loop instead of using foreach with your iterator. This is "easy money" to reduce GC and it doesn't make your code ugly or bloated, just a little less elegant.
The second principle you should follow is:
measure memory allocations to see when and where you should use with the first rule
Just for grins, try capturing the filter in a Linq query and holding onto the query instance. This might reduce memory reallocations each time the query is enumerated.
If nothing else, the statement preallocatedComponents.Where(r => r.Enabled) is a heck of a lot less code to look at to do the same thing as your yield return.
class ComponentPool<T> where T : DrawableGameComponent
{
List<T> preallocatedComponents;
IEnumerable<T> enabledComponentsFilter;
public ComponentPool()
{
enabledComponentsFilter = this.preallocatedComponents.Where(r => r.Enabled);
}
public IEnumerable<T> Components
{
get { return enabledComponentsFilter; }
}
...

Categories

Resources