- Home /
Design Advice: Power Up System (static variables?)
hey there,
I have a game in progress in which the player can fly around in 3d space and shoot weapons. I have various variables for the player like: movement speed, rate of fire, damage, hit points etc. I would like to create a system of powerups to modify these variables as the player's score increases.
I have a static variable for score in a game object that manages global stats. The player variables are on various game objects as children of the main player object.
I am trying to decide whether it makes more sense to write code for the changes into each script which controls the player variable (like put different power up modifiers in the gun script for example) and then have those check a static variable in the global stats to turn them on or off, or whether I should try to track all that in the global stats object and just set the different variables to new values from that object.
I guess the heart of the matter is: will I be better off having many scripts checking a static variable or variables as to the players state of progress or should I have my object tracking score linked to all the weapons etc and modifying their variables from logic inside the score tracking script? Hope the question is clear.
I know this is more of a design question than a strict scripting question, but I feel like the decision I make here will have wide ranging consequences including how organized my scripts are and for overall performance and wanted to seek some advice.
thanks in advance! M.
Just watched @Xevoius ' video (linked at bottom) implementing @Fattie 's GRID approach. I'm excited. And very confused.
What can Singletons do that Grids can ALSO do. What are their unique abilities???
Second of all... I'm wondering if anyone can take a look at "Toolbox" and tell me how it compares? It also claims to be an alternative to Singletons... http://wiki.unity3d.com/index.php/Toolbox
I'll ask again:
Can someone draw me an $$anonymous$$S Pain Venn diagram or table showing: (a) the things Singletons can do, (b) some things that both Singletons and Grids can do, and (c) things that only Grids can do. Why switch to Grids!?
I'm sure exactly what the Toolbox is doing yet. (Like would I use it along with Grids?)
PS. I'm a dummy. So bizarre metaphors and short videos and $$anonymous$$S Drawings are $$anonymous$$OST welcome.
That great video again, for reference: https://www.youtube.com/watch?v=lWmk2QXy4wU
P.S.S. I would love to know if Grids solve any of these issues https://blogs.msdn.microsoft.com/scottdensmore/2004/05/25/why-singletons-are-evil/
hi Sloth, this is all
INCREDIBLY OUT OF DATE
Just go here:
http://stackoverflow.com/a/35891919/294884
Everything you say about singletons is totally irrelevant. (There are no singletons in Unity, it's an ECS system.) Honestly there is absolutely nothing to think about or do these days. Just do what it explains in the linked post above!
If you must use "Grid" (ie to avoid typing one line of code) just go here http://answers.unity3d.com/answers/1124859/view.html
(the "toobox" thing is utter rubbish and like 10 years out of date)
honestly it is
JUST THIS SI$$anonymous$$PLE
http://stackoverflow.com/a/35891919/294884
there is literally nothing to it these days. it's a non-issue.
Sure, use a "Grid" script if you want to save one line of code.
Answer by Fattie · Mar 14, 2014 at 07:37 AM
it is honestly just this simple:
http://stackoverflow.com/a/35891919/294884
Use a "Grid" like this: Grid.cs
using Assets.scripts.network;
using UnityEngine;
static class Grid
{
public static Comms comms;
public static State state;
public static Launch launch;
public static INetworkCommunicator iNetworkCommunicator;
public static Sfx sfx;
static Grid()
{
GameObject g = GameObject.Find("_app");
comms = g.GetComponent<Comms>();
state = g.GetComponent<State>();
launch = g.GetComponent<Launch>();
iNetworkCommunicator = g.GetComponent<INetworkCommunicator>();
sfx = g.GetComponent<Sfx>();
}
}
Then, anywhere in the project you can say
Grid.sfx.Explosions();
and so on. Be sure to read this http://stackoverflow.com/a/35891919/294884
Be aware of incredibly out of date discussions on this topic on the web; there are 100s of pages of total crap out there, which is now completely irrelevant.
Just wanted to double back and say that I implemented this system and it's A$$anonymous$$AZING!!!!
In addition to being able to fire off whatever functions I wanted from whatever script I also used this to replace a bunch of GetComponent uses where I was passing variables between scripts. By using this setup I've been able to reduce my use of GetComponent by about 80%. Wonderful! I think this aspect of this was actually a way bigger time/headache/efficiency saver for me.
This has really opened a world of usefulness for me.
A few questions:
1) Is the way I'm using this to pass variables back and forth between scripts efficient? Is it Ok to for example put something in an update function that is continuously accessing a variable, for example:
void FixedUpdate (){
speed = Grid.playerAllStats.playerSpeed;
//do more physics stuff
}
Actually I ended up finding a better way to script that without putting that in update, but I'm still wondering about how fast this is in general.
2) Do I need to set my __PlayerAllStats and __Proc$$anonymous$$anagerGrid (for example) objects that are in my preEverythingScene to DontDestroyOnLoad? I did it for one of them but then forgot to do it for my second one and it seemed to work any way. Confusing.
Anyway, thanks again!
@Xevoius It gets a little more cumbersome because you have to hit play from the prescene, so you may end up swapping back and forth between scenes as you work.
For my project it hasn't been too much of a problem because I'm working mostly on scripts and prefabs and so I dont need to have that scene open to tweak. I just make changes to the assets with PreScene loaded and then launch the main scene via script. If anyone has a more slick way to handle this though it would be cool.
Hey $$anonymous$$irrorfish!
When you are working in Unity, you always have to go to your loading scene (your scene zero) before hitting play.
It's just how it is working with Unity.
Every Unity project (other than just a test project) will have a "pre-loading" scene.
Here's a very trivial solution to automate "going back to the zero scene" (at the bottom of the page...) http://stackoverflow.com/a/35891919/294884
Fattie, I see how much you post and how you help so many people, so let it be known I appreciate that before I start this next section.
First and foremost, I really HATE how you're talking in such a factual way when this is purely subjective and very opinionated. I feel like somebody told you a singleton is bad practice at some point in your life so now you avoid them like the plague for no good reason.
I actually agree having a preload scene is useful (I use them myself), but the fact you don't make your _app a singleton baffles me. At the very least, devs now have to press play from the preload scene to ensure their systems are running (this alone is horrendous), when in fact you could have the _app object on all scenes implemented as a singleton and the play button would work from anywhere. When the game is built/run from preload the additional _apps would be destroyed without any conflicts or problems.
Another horrible concept you've got here is telling devs to find references by using FindObjectOfType and then manually caching the reference in each script which needs it... JUST so you don't use a static instance. At least I HOPE you're expecting them to set them as cached references and not FindObjectOfType every time... or else we've got an even deeper issue. You are taking an incredibly valuable program$$anonymous$$g concept which is used widely, throwing it in the bin and giving them a sh*t sandwich in return.
I wouldn't of attacked this post if it wasn't for the factual way you wrote the posts. You may have helped thousands of people on these forums over the years, but I truly believe you've set every dev who read this post and took it to heart in a bad direction.
Hey @Tarodev , thanks for writing this as I was about to write the same thing after seeing Fattie posts everywhere.
The pattern he describes is useful, but the dogmatic way he talks about it is totally off putting. There's a post where he just says, all caps "THERE IS NO OTHER WAY", which was almost enough to convince me that this is a terrible design (because, generally speaking, people who very strongly say there's no other way are pushing a narrative that is not strong enough to stand on its own)
One GameManager with a singleton that references other managers is fine, GetComponent in the constructor to cache the results is fine, but you can also have serialized fields and link to one object per manager, or make your "grid" (what a terrible name, by the way !) a component and use its Awake(). A persistent scene with DontDestroyOnLoad() is great, too.
Contrary to what some random zealot wants you to believe, there's more than one pattern and design solution to your Unity game issues.
Cheers
Hey Fattie!
Thanks for the link, that's a great solution!
$$anonymous$$.
Fattie, here is what I believe you have been after.
Game Pre-loading Setup Configuration
1) Add all the persistent objects/components to a Pre-Game Loading Scene
2) Add the Grid and SceneAutoLoader scripts to the project - do not need to be attached to an object Grid Script: http://answers.unity3d.com/questions/663351/design-advice-power-up-system-static-variables.html#comment-684020 SceneAutoLoader: http://wiki.unity3d.com/index.php/SceneAutoLoader
3) $$anonymous$$ake sure this has been added to the Grid code:
#if UNITY_EDITOR
using UnityEditor;
#endif
...
//add this below component code
#if UNITY_EDITOR
Application.LoadLevel(System.IO.Path.GetFileNameWithoutExtension(EditorPrefs.GetString("SceneAutoLoader.PreviousScene")),true);
#endif
4) $$anonymous$$ake sure and wrap the SceneAutoLoader code in this
#if UNITY_EDITOR
...
#endif
5) Add the Pre-Game Loader persistent components to the Grid constructor code 6) Reference the Grid at least once in one of the persistent object Start() or Awake() to make sure constructor gets called 7) Add this to all persistent component scripts
void Awake()
{
DontDestroyOnLoad(gameObject);
}
8) Configure the ScreenAutoLoader File->Scene Autoload menu option to point to my Pre-Game Loading screen
9) $$anonymous$$ake sure all scenes required have been added to the build
10) Press Play
This automatically reloads the scene you are working on in the editor after the pre-game scene has been loaded.
I want to test the workflow a bit to make sure it is a working solution for me. Then I intend to put together a video on YouTube to give a step by step on how to set your bootstrap scene method up.
Let me know how it goes.
~Cheers
Your answer
Follow this Question
Related Questions
Damager Powerup issue - NullReferenceException: Object reference not set to an instance of an object 2 Answers
GIVING variables to another gameobject 2 Answers
Get the child gameObject of a parent and not the Transform 4 Answers
Can't understand generic getComponent for Js 1 Answer
Changing TextMesh text via script 2 Answers