Passing more parameters to Action Efficient? - c#

I have an Action callback called Action<GameObject,GameState,GameObject,Vector3> onCutCB;
I have 5 Scripts that references a function called
void OnCut(GameObject survivalObj,GameState state,GameObject
destroyObj,Vector3 startPos){
////
}
but the problem is that out of these 5 scripts ,first scripts need 3 parameter,second script need all parameters ,rest of the scripts need one parameter
So the question is
1) should i use callback or call the functions manually from by using the reference of the respective classes
2) As i am passing 4 parameters out of which some parameters are useful in some scripts will there be more garbage collection ? than calling the scripts method manually ?
Out of the four parameters i passed 2 are reference type and 2 are value types.

1) should i use callback or call the functions manually from by using
the reference of the respective classes
Calling functions directly is faster but this shouldn't be a problem at all. It doesn't make that much difference.
2) As i am passing 4 parameters out of which some parameters are
useful in some scripts will there be more garbage collection ? than
calling the scripts method manually ? Out of the four parameters i
passed 2 are reference type and 2 are value types.
No, there will be no memory allocation when you pass more parameter to a delegate. The only time memory will be allocated is when you initialize the onCutCB variable. For example, onCutCB = OnCut;. That's why onCutCB must be initialized in the Start or Awake function once. When onCutCB in invoked, memory allocation does not happen.
Read the comments in the code below to see where memory is allocation or not:
Action<GameObject, GameState, GameObject, Vector3> onCutCB;
void OnCut(GameObject survivalObj, GameState state, GameObject
destroyObj, Vector3 startPos = default(Vector3))
{
}
void Start()
{
//MEMORY IS ALLOCATION
onCutCB = OnCut;
}
void Update()
{
//NO MEMORY ALLOCATION HERE
onCutCB(objToUse, gameState, anotherObj, thePos);
}
though when i was playing my game on mobile devices til to minitues it
works fine but after that some times its lags a bit I am using object
pooling also when i restart the game my scene doesnt load i just use
pooling because the gameobject which were instantiated were required.
This problem you described has nothing to do with the gradual slow-down of your game. You are either instantiating many Objects non-stop, starting a coroutine every frame from the Update function and coroutine does not end/stop or something that adds up to the execution time.
Without your all scripts, it is impossible to tell what's causing your problem. Please, do not edit your question with all your code. Find and fix the problem yourself.
Use the Profiler!
Go to Windows --> Profiler then enable Deep Profiler and click on "Record" and clicl the Play button. You will see which script is allocating memory and how much time it takes for each function to complete. Look into these and fix it.
Here is a full Unity tutorial on how to use the Profiler.

Related

What methods are called by which scene's objects on start?

Is there a way to check what methods exactly are called on scene's start? And which objects called them? I want to achieve something similar to adding Debug.Log(); to every single method but without doing it. I'd like to know what's going on in a project when I press play.
A scene consists only of game objects (there's nothing else in Unity).
GameObjects may have 1 or more Components attached.
When you click Play ...
It looks like you already know that, the calls such as
void Start()
(if they exist in the script) are called - automatically, by Unity - when each Component on each GameObject is launched with the scene.
It's quite common that inside each Start, you just add something like Debug.Log("starting, script name, on .. " + transform.name) which will simply let you know that that component on that game object has started.
Maybe that's what you need.
Obviously you will have added many functions to your own scripts
void SomeFunction() {
Are you saying you want to know when those functions run?
If so the only way to do that is simply manually add a Debug line, inside each function.
(Regarding functions which you add yourself, example SomeFunction, they are not in any way called automatically. They are only called if you call them (say from Start or similar). You can be sure they are only called if you call them.

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.

Creating new objects in the Update() method

I read somewhere that I shouldn't create any new object instance in the Update() method of the game engine, because this will lead to wake Garbage Collector up and decrease performance, but sometimes I see in some tutorials that they use new keyword in unity Update() method! Is this okay? And unity will handle this in someway, or no?
This is a confusing thing for new C# programmers.
Is this okay?
The answer to this depends on the datatype that you using the new keyword on. This is basically value type vs reference type. See the link at the end of this answer for more information on this.
If it is a class, then don't use the new keyword on it in the
Update function. Use Object Pooling or you will be creating new Object every frame. Yes, this is costly.
If it is a struct, you can freely use the new keyword on it in
the Update function without.
You may have seen a code like this in the Update function:
Vector3 vec = new Vector3(0, 0, 0);
That's fine because Unity's Vector3 is a struct not a class.
Another example is this in the Update function:
GameObject obj = new GameObject("MyObject");
This is bad because GameObject is a class. You are creating a GameObject each frame. Do this once in the Start function then re-use it. You can also use object pooling.
Notice the circled text in red color, you can use that to determine if the API you are using is a class or a struct.
Here are other things to know:
1.C# value type vs reference type
2.is there a point in recycling value types unity
3.What's the difference between struct and class in .NET?
4.Object Pooling in Unity
Note that this answer focuses on using the new keyword in Unity as mentioned in your question. There are still other things that can allocate memory without even using the new keyword. Examples includes using the param keyword in a function parameter, returning an array in a function, using yield return 0 instead of yield return null.
And unity will handle this in someway, or no?
The only one that can answer this question is the device you are running this code on. Usually, you get some hiccups on mobile devices due to GC running. Object Pooling is very important on mobile devices.

Avoid to use 'Update'?

I have a seperate script of time which I use to show time in my scene. It contains hour and minute and seconds variable.I want to do some specified work e.g., code execution on specified time and currently i am doing something like this. in Update. I am running a function which check continously check time variable in order to run an animation.
void Update()
{
checkTrainArriveTime();
}
void checkTrainArriveTime()
{
if (timeManager.GetComponent<Scale2>().hour == trainArriveTimeHour && timeManager.GetComponent<Scale2>().min == trainArriveTimeMin
&& isTrainArriveConditionExecute)
{
isTrainArriveConditionExecute = false;
PlayAnimationClip("Start");
}
else if (timeManager.GetComponent<Scale2>().min != trainArriveTimeMin)
{
isTrainArriveConditionExecute = true;
}
}
As Time will match this function will play the animation. Now I have 50 script attached to 50 different game Object. It is
working fine but It definitely not the right way to use Update Event. In my code, It is necessary to check time on every frame and
extra load on update. Is there any efficient way to do this Job?.
I can see your struggle. You are right, it is definitely not the best way forward.
The best option I can see here would be creating Animation Manager which is a singleton instance (there is only one instance allowed per application).
I would suggest moving your animation triggering logic to an Update method of AnimationManager.
Once you have done that. You will be able to access its instance calling AnimationManager.getInstance() method.
Next step is creating internal registry that would be nothing else than just a list of your registered game objects that you want to trigger animation for.
I don't know what exactly is your timeManager but I can imagine it is probably an instance of TimeManager controller that you drag and drop onto your public timeManager property. Consider turning it into singleton as well or at least moving assignment of timeManager.GetComponent<Scale2>() into Awake() method.
It is important to not to call GetComponent() method from inside of Update()', as it has an impact on performance.GetComponent` is quite expensive to call.
Hope it helps.

Return directly to caller of caller and restore state on next call

I'm building a plugin to a system. My plugin's update() method is called occasionally by the system.
In my plugin's update() method, I'm modifying the systems state, however the system state isn't updated until the system has had a chance to do so (this happens between invocations of the update method).
So whenever I do a system updating method I'll have to return all the way out of the update(), for it to return, and re-enter, and then I'll have to try to get back to where I was. I've been considering a smarter way to do this, namely by saving call frame, and such. And then loading that call-frame on return.
But instead of starting to implement this on my own, I was considering whether there was already a way to do this. The plugin I'm writing is in Lua, via the NLua library for C#.
I'm able to access the C# environment, if needed!
I have an idea, that I need something like a continuation?
Example of what I'd love to have;
update() --> ... --> helper_function() --> system_state_modifier()
// System state modifier changes system state, saves the current stack/registers,
// whatever else is needed, and returns directly to update()'s caller
// On the next call to update, the previous stack/registers and such
// is restored, and continued.
I was indeed looking for coroutines, they seem to do exactly what I want.
I ended up wrapping my update() can in a method to run the actual update function as a coroutine, and wrapping all my system state changing methods, with coroutine.yield()
Although the coroutine route is quite nice, another option might be, depending on constraints (like if you can pass obj to script) for the stack & registers to be put in a struct that is given as part of call:
struct StackAndRegisters { ... }
StackAndRegisters sar; // outside update loop
// then at every call:
update(sar) -> -> ... --> helper_function(sar) --> system_state_modifier(sar)
// system_state_modifier modifies sar

Categories

Resources