3
\$\begingroup\$

In the code I'm doing, I usually use global and local variables, as recommended.

If the variable is not going to be used in more than any method, I make it local, otherwise, I make it global.

In addition to using local variables with things that don't happen all the time, but every now and then. The player's shot for example: receives the value of a script that contains the player's data.

But I know that this isn't always clear, especially since I'm working on Unity.

Suppose the following situation:

I usually separate scripts by function, so I know exactly where to look when I want to modify something and also to completely replace it if I want to.

  • script_admGame - in this script will be the player's health, damage and movement speed;
  • script_playerMovement - in this script is that the character's movement will be programmed, taking the variable from the other script (script_admGame);

void Update()
{
    if (Input.GetKey(KeyCode.W))
    {
        GameObject obj_adm = GameObject.Find("obj_adm");
        int moveSpeed = obj_adm.GetComponent<script_admGameControl>().moveSpeed;
    
        //any example
        transform.position += new Vector3(0,0,moveSpeed * Time.DeltaTime);
    }
}

I have two fears:

  • be making minimal and irrelevant optimization savings;
  • be saving memory, but overloading the processor/cpu;

That's because some functions are expensive to process (I don't know how interesting it is to run a function every frame instead of having one more variable in the script in question).

Another important thing is that this speed can change if the player collects certain items, so it doesn't have a fixed value.

As an alternative to the code shown above, I thought of making the character movement public in the script. Which would initially receive the value of script_admGame and would sporadically undergo modifications when colliding with items, receiving a certain type of attack, etc.

In short, I would like to know precisely when to use each type of variable in unusual situations. Something like a general rule or convention. Or a way to check and compare two different applications.

Link I read about but didn't give a clear picture of the situation I'm in doubt (pt-br):

https://bookdown.org/jessicakubrusly/programacao-estatistica/funcoes-e-var-local.html

https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/classes-and-structs/implicitly-typed-local-variables

\$\endgroup\$
4
  • 2
    \$\begingroup\$ I usually use global and local variables, as recommended I'm not sure if it's a Unity thing specifically (I'm yet to learn it, though very interested), but haven't global variables being frowned upon for a long time already? \$\endgroup\$
    – Josh Part
    Jun 17 at 15:27
  • 1
    \$\begingroup\$ All variables can be classified as global or local. If you aren't using global variables or local variables, you aren't using variables at all, so your first sentence isn't really saying anything. \$\endgroup\$
    – chepner
    Jun 18 at 13:37
  • \$\begingroup\$ @JoshPart A private variable is global to the entire script in which it is contained. The public one can be accessed by all other scripts. A local variable only exists within the method where it is declared (void start/update/any). \$\endgroup\$ Jun 18 at 21:46
  • 1
    \$\begingroup\$ Yeah, I'm aware of that. What I say is that, as far as I remember, global variables have been considered a bad practice (or a "not very good" one at least, e.g. this question) from a long, long time. I'm just pointing that out from the part where you say that you usually use locals and globals as recommended. \$\endgroup\$
    – Josh Part
    Jun 20 at 15:18

2 Answers 2

10
\$\begingroup\$

Don't search for something every frame if you can store it.

// Make a member variable (NOT a "global") to cache a reference to your dependencies.
script_admGameControl _gameControl;

// Pay the search cost only once.
void Start() {
    _gameControl = FindObjectOfType<script_admGameControl>();
}

void Update() {    
    if (Input.GetKey(KeyCode.W))
    {
        // Don't forget to scale by time when trying to move at a consistent speed.
        transform.position += new Vector3(0,0,_gameControl.moveSpeed * Time.deltaTime);
    }
}

The memory it costs to store one reference is trivial - a matter of bytes. The cost to search your entire scene for an object with a matching name, and to search that object for a matching component, grows with the number of objects in your scene and the number of components on that object. It's ridiculous to pay that cost every frame when you don't expect the answer to change frequently.

\$\endgroup\$
6
  • \$\begingroup\$ I edited the example code, at the time I ended up slipping, but the local variables are only created when the character moves. \$\endgroup\$ Jun 16 at 22:38
  • \$\begingroup\$ From what I've seen from your answer, even if this assignment is only done when the character moves, it would still be better to store it only once. If instead of GetKey it was GetKeyDown, would the question become relevant? \$\endgroup\$ Jun 16 at 22:46
  • \$\begingroup\$ I would consider FindObjectOfType to be a form of search, and only use it in certain circumstances. \$\endgroup\$
    – Evorlor
    Jun 17 at 0:07
  • 2
    \$\begingroup\$ The character moving is not a rare or unusual event. The player will press keys a lot, so it's better to have the stuff you need to react to those key presses ready at hand, rather than searching for it unnecessarily. And memory is not that precious that you need to be so aggressive in eliminating member variables. \$\endgroup\$
    – DMGregory
    Jun 17 at 0:42
  • 1
    \$\begingroup\$ @BonecoSinforoso - if your player moves for 2 seconds @ 60fps, that's 120 searches for the same object, vs one call in Start() when the script is loaded/enabled. It depends on the type of game and the style of gameplay, but consider an over-the-shoulder shooter, or a FPS like Counter Strike: unless you're camping, you're basically holding some directional key all the time (with 'W' being something like 80% of that). \$\endgroup\$ Jun 17 at 14:24
3
\$\begingroup\$

If you can have a reference, use the reference. Never* search. If you cannot maintain a reference, something usually smells.

*There are situations where searching is the best path forward. An example of when you should use search is if you are adding the components at runtime, and don't want to create unnecessary dependencies. Another example is when you are just hacking something together. But both of these examples smell.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .