Do I really have to declare all those variables at the top? Mine is quite a simple project, this specific script controls the weather in the game. If I have so many variables for such a simple script I can’t imagine how it will look when things get bigger!
I use all those GameObject.Find() in the start object because I don’t want to drag them manually into a public field in the inspector as I think that approach is more error-prone. This approach adds a substantial amount of time to the level-loading as Find() isn’t the fastest method. Should I just drag them in the inspector or is there any other best practice?
Please post you code as suggested in this thread. That makes it easier for us to do suggestions as to what you can improve.
As for your questions:
Well, you declare variables at the top by convention, so as far as that goes; yes. Whether or not you need all those variables at the top for your specific script, you’ll need to post the entire script for anyone to be able to tell you.
Just wait until you make a typo No, I always prefare dragging an object to a field instead of using strings to identify objects, as that is imo a lot less error prone (always try to use specific types instead of the general GameObject for these fields to reduce the chances for errors.
Hi there, personnally I usually use the C# region blocks to keep things tidy.
I also have a very clear way of organizing my scripts, resulting of years of experience using unity.
If you’re curious about it, my scripts go like this:
using UnityEngine;
using System.Collections.Generic;
namespace MyGame.MyCategory.MySubCategory
{
public class MyScript : MonoBehaviour
{
#region Input Data
//Stuff that should/can be set in inspector
public float _aCoolFloatValue;
#endregion
#region Members
//private members
int _aNiceIntegerValue;
#endregion
#region Unity
//all the unity magic methods like Awake, Start, Update, OnTriggerEnter...
void Awake()
{
}
#endregion
#region Triggers
//Stuff that can be called from outside, wether directly or through SendMessage
public void DoSomething()
{
}
#endregion
#region Helpers
//specific smaller/sub tasks which get split into methods that are used internally go here
void MenialTask()
{
}
#endregion
#region Data types
//Good way of storing various data that belong together, works well in inspector even in arrays or list
[System.Serializable]
public class MyData
{
}
//Looks clean in the inspector so i abuse it
public enum MyEnum
{
}
#endregion
}
}
When necessary I can also have events or properties regions.
This all folds nicely and I always know where to look for specific stuff even years after writing it.
Hope it helps !
PS: Regarding the use of Find(), if I may add, you’re dependent on object names when using it so I don’t think it’s less error prone than wiring things in the inspector, it also prevents you from reusing your component with otherwise named objects. Wiring in the inspector is just the way you do things in Unity, it differs from what you may be used to in other environnement but that’s how we roll here .
You can imagine all kinds of structures but efficient ways of getting references to objects will involve wiring things in the inspector or keeping references of spawned object (and if you spawn them it probably means you have a reference to a prefab that you wired in the inspector anyways )
Whatever the faults of Find (and yes, you should drag objects in the inspector for reasons stated above), it doesn’t add any noticeable time to level-loading. When people say Find is “slow”, that’s relative, as in doing it hundreds/thousands of times per frame, compared to direct references. It’s not slow as in “can time it with a stop watch”…we’re talking microseconds here, depending on how many objects are in the scene.
the one thing that stands out to me is that you’re dealing with all the “bits” individually… to me it would make more sense to group the animator/sound/particle/whatever into a data class/structure, and then reference to that data structure. So instead of “find the rain particles, find the rain sound, find the rain this, find the rain that, find the rain other” you just “find the rain weather dataobject”. You then might also want to consider using something like a dictionary to store the references to the weather effect dataobjects, you can then add in another one without needing to rewrite everything.
You could probably make things much easier on yourself by having a rain controller, a day-night controller, a lightning controller and so on. Then your main MeteoController uses those scripts instead of having to worry about a ton of variables.
Find() is generally a bad idea because it’s based on thing’s names. So if you know that there’s a bunch of Find calls around, you suddenly can’t rename anything, since there’s a non-zero probability that some other script’s reliant on the naming.
Especially if you work with other people, that’ll be a nightmare.
I would consider ditching the module storage. As far as I’m aware accessing a particle system module is a direct reference. So there is little to no value to caching it. That will cut the amount of variables down dramatically.
But overall I think @Baste is right. Why is one script controlling lightening, rain, and snow. Better to have a script for each, and then if you need it you can build a master script to rule them all.