Refactor/Rename Unity inspector variable names? - c#

Refactoring or renaming member variables is commonplace in software development, but this can be difficult while working in Unity. If a variable is visible to the inspector the old variable is destroyed, along with whatever value set, and a new variable is created. Is there a way to tell Unity that this new variable is the same as the old one preserving the values set in the inspector for all instances of the component?

Yes, there's a way -- use the FormerlySerializedAs attribute:
[FormerlySerializedAs("theOldName")]
[SerializeField] float theNewName = 0f;
(An alternative, brute force approach is to do a text search & replace in the scene file to rename something, by the way.)

Related

How to assign variables in the inspector for a script on an instantiated object?

Good evening.
So I want to assign a text box to an instantiated object but how do I go about doing this via code and not manually. As hundreds of these prefabs could be instantiated I need to be able to assign the text box in the inspector via code at runtime (As in when they are created).
Just to note: all these fields are assigned on the object that this prefab is a clone of, just for some reason the scripts copy over but the assigned values don't?
Let me know if you need to see any code but I think the question explains enough.
Thank you in advance!
https://gamedev.stackexchange.com/questions/135209/how-to-store-references-to-scene-objects-in-prefabs - This post answers my question. (It is a set of ways to assgn variabkes to prefabs in the inspector).
I thought I might as well repost it here as the answer is on a different forum.
GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
bullet.GetComponent<BulletScript>().shooter = gameObject;
Seems to be the best way to do it, using GetComponent to decidd what script you want to assign something to and then assigning that part using .variable = whatever you want it to be.

Destroying Instantiated Clone Components Breaks Original Game Object Components?

Maybe im missing something obvious but to keep it short. I have working code for a character. When you "dash" I want to leave behind an after-image type effect, by cloning the player, removing its unneeded components and then applying a shader. Issue is as soon as I instantiate the clone the original player stops functioning (cant move etc). It still has all its components and everything as normal, and the clone does get the correct components removed. But it still breaks. As soon as I remove that line, its back to normal. Any ideas?
This is the only relevant code in the script that instantiates the clone.
private void DodgeEffect()
{
GameObject _DodgeSFX = Instantiate(gameObject, transform.position, transform.rotation );
Destroy(_DodgeSFX.GetComponent<PlayerController>());
Destroy(_DodgeSFX.GetComponent<PlayerCombat>());
Destroy(_DodgeSFX.GetComponent<WarpController>());
Destroy(_DodgeSFX.GetComponent<Animator>());
}
its because you are making a copy of gameObject. while Instantiate() returns a GameObject, it also returns whatever you put into the first section of the method. instead, make a seperate gameObject than the player in the editor, and make _DodgeSFX public so you can put the copy into the slot. Then, just instantiate that seperate GameObject and you wont have to destroy the components through script(because you remove the components in the editor), saving time
Ok so from some testing I think its down to the Unity.InputSystem only allowing 1 instance of each Input to be enabled at once. When I instantiated a clone of the player, it still goes through the Enable/Awake functions before those components are destroyed, and since the Inputs on that clone were never disabled, that becomes the "main" one. If I set the main player's scripts with Inputs deactive and then active again, it all works as normal. Note that the script was still working on the main character just fine, it was only the inputs that was broken. Im still not sure why this is the case, if its a limitation of the input system, or intentional, cant seem to find documentation of this experience anywhere.

Spawning gameobjects relative to the position, width and length of another gameobject?

I'm currently developing a game in Unity using C# and I've run into a small problem.
I need to spawn a certain gameobjects relative to the Spawnposition and length of another game object. Now I figured that bounds.size would be the best function to use in this instance. As shown bellow I declare first the variable that uses this in my start method:
public void Start()
{
GameObject PointBar = (GameObject) Resources.Load("PointBar Horizontal");
PointBarVectorLength = PointBar.GetComponent<BoxCollider2D>().bounds.size.x;
PointBarVectorConv = Camera.main.WorldToViewportPoint(new Vector2(PointBarVectorLength, 0f));
}
However, the gameobjects in question are inactive at start's call and thus I presume don't return any value for bounds.size when called.
Does anyone know how I can access the bounds.size or equivalent of an inactive gameobject or is there something else I'm missing here?
As noted in the documentation for the Collider.bounds property, bounds "will be an empty bounding box if the collider is disabled or the game object is inactive". So your assumption was pretty much right. Since the object doesn't exist in worldspace that makes sense.
I'm not sure about the most elegant solution for your use case but two options spring to mind.
Calculate the object's spawn dimensions by accessing its transform.localScale and factoring in the scale of prospective parent objects. That could get messy but you could probably also write a helper method to make it more manageable.
Instantiate the object somewhere off screen after you load it, access its Collider.bounds property to get the information you need then move it where ever you want it or store the information for later.
There may be better solutions but that's what leaps to mind for me.
I solved the issue by using GetComponent().bounds.size.x;
instead of BoxCollider. This component can get accessed when the game object is not active.

Is setting values in inspector the same as setting default values in Unity?

I am very new to Unity, so this might be a dumb question, but is setting values in inspector the same as setting default values in code?
Example:
public string name; //then go to inspector and set it as "Bob".
or
public string name = "Bob";
So, to rephrase, will these actions above achieve the same effect?
will these actions above achieve the same effect?
Yes, they will both accomplish the-same thing. They will both initialize the name variable with the "Bob" value once you click the "Play" button.
It's highly recommended that you don't set the default value from code if you make the field variable to be public. The reason for this is because you will run into a bug that will take you time to discover and fix.
For example, lets say you had this:
public string name = "Bob";
Then you go to the Editor to let it compile. Later on, you went back to the code and changed it to "Jake":
public string name = "Jake";
While programming, you would still think that the value is now "Jake" and expecting your code to do something based on "Jake" value. This will fail since name is still "Bob". The latest value of name variable is shown in the Editor until the name variable renamed or the script/component that holds the name variable is reset:
This is a time waster issue and yes, some people still go through it. If you want to make the variable public but don't want to assign it from the Editor, use the [HideInInspector] attribute to hide it.
[HideInInspector]
public string name = "Bob";
This will make sure you won't mistakenly change it in the Editor and cause issues while allowing your variable to be accessed from other scripts.
This only applies where the variable is declared. You can change the variable in function or property later on and the changes should take effect without any issues.
Not exactly: as soon as you attach your script to an object for the first time, and you have global variables initialized into its code, Unity sets the corresponding Inspector's values with those.
But, once a variable is set in the Inspector, you can change that only by the Inspector itself, and no more by code.
Obviously, this just applies for types that do not depend by assets (primitives, Vector2, Vector3, etc...). In case of Prefabs, Materials, etc... the only way is by always passing from the Inspector, of course.
In conclusion: never rely on code initialization! Always make sure that by Inspector they are set correctly as you want.

How to pass a variable to a script in another scene

I have a main menu for a game where you can select difficulties, easy, normal etc.
Currently, I load a separate scene for each difficulty, I have a scene for easy, a scene for normal, hard, etc.
I know you can pass variables between scenes, such as
something.GetComponent<someScript>().someVariable
But how do you pass a variable to a script on a GameObject that doesn't exist yet?
You could use PlayerPrefs to solve this issue. For example, in your script on your main menu where the difficulty is set you would say:
PlayerPrefs.SetString("Difficulty", "Medium");
Then in your next scene, when you need to access that variable on a different script, simply use:
String difficulty = PlayerPrefs.GetString("Difficulty");
You could also look at using DontDestroyOnLoad to keep track of your variables on a persistent script which stays with you on an object that remains loaded even as scenes change. Then you could access the variables you need similar to how you have already described.
To have the variable available in the next scene, the standard way is to have a game object that doesn't get destroyed when the scene changes. You do this by calling DontDestroyOnload() in any script on that game object, e.g.
void Awake () {
DonDestroyOnLoad(gameObject);
}
You can use an existing game object or create one just for this purpose, with a single script that calls DontDestroyOnload() and also has variables that you want to pass to the next scene. You can set the variables, before loading the next scene, like in your example code:
someGameObject.GetComponent<GameVariablesScript>().someVariable = someValue;

Categories