Unity3D/C# - add a variable to gameobject - c#

How can I add a variable to a GameObject?
GameObjects have a series of variables (name, transform, ...) that can be accessed and modified from any script. How could I add a variable such as for example "color" or "type" that could be accessed or modified from other scripts.
Thanks.

If GameObject wasn't a sealed class then inheritance could have been the solution to your problem. In this ideal situation you could try the following.
public class ExtraGameObject : GameObject
{
// Logically you could make use of an enum for the
// color but I picked the string to write this example faster.
public string Color { get; set; }
}
A solution to your problem could be to declare your class like below:
public class ExtraGameObject
{
public string Color { get; set; }
public GameObject GameObject { get; set; }
}
I am aware of this that this is not exactly that you want, but that you want I don't think that it can be done due to the sealed nature of GameObject.

As every object in c# GameObject class inheritance Object class. If you right click on GameObject and select go to definition you will see that below.
In order to reach one object's variables you need a reference(not considering static variables). So if you want to change variables of one GameObject from other you need a ref.
On Unity inspector you can assign values to public variables of a script. Below you can see Obj end of the arrow. Now assign cube(is a GameObject ) to Obj.
After drag and drop
Now you can reach every subComponent of cube object. In red rectangle I reached it's Transform component and changed it's position.
I hope I understood your question correct.GL.

Christos answer is correct. You cannot add a variable to the GameObject datatype because it was built into the language as a base. To add variables to premade data type, extend off of them. For more information on inheritance see
https://msdn.microsoft.com/library/ms173149(v=vs.100).aspx

You can add a script to the prefab from which an object is created using the Instantiate method. In this script, you declare public variable.
Then you can change and get the value of this variable using the GetComponent method.
The code in script file added to the prefab (prefab name is thatPrefab, script file name is IdDeclarer) as a component:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IdDeclarer : MonoBehaviour
{
public int id;
}
Declaring an object's characteristics (ID in example):
GameObject newObject = Instantiate(thatPrefab, new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
newObject.GetComponent<IdDeclarer>().id = 99;
Debug.Log(newObject.GetComponent<IdDeclarer>().id);
Output: 99
I hope I helped you

Related

How to access the value of cinemachine's camera distance in Unity / C#?

I'm working on Unity/C# now and I'm stuck with accessing CinemachineVirtualCamera's camera distance value in the script. What I'm trying to do is change the value of camera distance in the body section.
First of all, how can I access the CinemachineVirtualCamera component in this game object? The MoveScript is what I attached to a player game object, and I want to zoom out the camera depending on the player's movement. Since the game I'm making is small, I won't make other .cs files.
I wrote
public class MoveScript: MonoBehaviour
{
private GameObject camObj;
void Start()
{
camObj = GameObject.Find("Vertical Follow Camera");
camObj.GetComponent<CinemachineVirtualCamera>(); // <- but I get error saying, The type or namespace name 'CinemachineVirtualCamera' could not be found
}
}
I also read this document and I think the m_CameraDistance is what I'm looking for but how can I access that value?
For anyone else who wondering
GetComponent<CinemachineVirtualCamera>()
.GetCinemachineComponent<CinemachineFramingTransposer>()
.m_CameraDistance
As stated in the linked document, these classes are in Cinemachine namespace. To access the classes you have to either add
using Cinemachine;
to the beginning of your script or change your script to
public class MoveScript: MonoBehaviour
{
private GameObject camObj;
void Start()
{
camObj = GameObject.Find("Vertical Follow Camera");
camObj.GetComponent<Cinemachine.CinemachineVirtualCamera>();
}
}
And as for accessing the m_CameraDistance variable, HuySora already answered that part
Try this and don't forgot to mention namespace
public class MoveScript: MonoBehaviour
{
private CinemachineVirtualCamera virtualCamera;
private GameObject camObj;
void Start()
{
camObj = GameObject.Find("Vertical Follow Camera");
virtualCamera = camObj.GetComponent<CinemachineVirtualCamera>();
float f = virtualCamera.m_CameraDistance;
}
}

Accessing other script method from instantiated object [duplicate]

This question already has answers here:
Store References to Scene Objects in prefabs?
(1 answer)
How can I grab a reference of a game-object in a scene from a prefab
(1 answer)
Closed 2 years ago.
I am trying to set my game up to where there is a player, you touch the screen to throw the object, once that object collides with another object 1 point is added to the score. I added a script to the instantiated object that prints a message, to the console, when a collision is detected. The script also has a reference to another script holding the score variable.
The script is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CrackEgg : MonoBehaviour
{
public Stats stats;
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "BreakEgg")
{
stats.DepositMoney();
Debug.Log("I am actually working");
}
}
}
The Stats script is:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Stats : MonoBehaviour
{
[Header("Bank")]
public int bankAmount;
public int depositAmount;
public void DepositMoney()
{
bankAmount += depositAmount;
}
}
I know I have to have the Stats script attached to a game object(I have it attached to an empty game object). The thrown object is a prefab and has the CrackEgg script as a component. I try to drag the Stats game object into the Stats field of the CrackEgg script but it doesn't work. It only works if the Stats game object is also a prefab. The main issue I'm having is that even when I have the Stats game object prefab in the hierarchy, when I test the code, the bankAmount variable does not increase at all. As a summary, I want the instantiated object to detect a collision then run the DepositMoney() method, from the Stats script, but am not able to find a way to make it work.
Quick check: create a CrackEgg on the scene. Try to drag the Stats object into the field. It should work. Now drag this CrackEgg to the Project View in order to create a prefab. The Stats field is empty on the prefab. Why?
A prefab can be instantiated anywhere in your game, so it's possible this reference to a scene object is not valid in case the prefab is instantiated in another scene.
So you must get the reference to the Stats object in runtime.
You can accomplish that in two ways:
METHOD 1
Tag your Stats object with a "Stats" tag.
Then locate it in the scene whenever you start a CrackEgg.
class CrackEgg : MonoBehaviour {
void Start() {
stats = GameObject.FindGameObjectWithTag("Stats").GetComponent<Stats>();
}
}
METHOD 2
Make your Stats class static, and not a MonoBehaviour component.
public class Stats
{
private static int bankAmount;
public static void DepositMoney(int depositAmount)
{
bankAmount += depositAmount;
}
}
Then you don't add it to any object, since there's always a single instance of each parameter on the program. This is an usual pattern for score classes.
To access it, you don't need to store a reference to Stats, just use the class name:
if (collision.gameObject.tag == "BreakEgg")
{
Stats.DepositMoney(depositAmount);
Debug.Log("I am actually working");
}
Since you can't assign values to static classes on the Editor, I've suggested a modification where the caller defines the deposit amount when calling. You might need to think about the safety issues (don't allow values out of a range, etc).
Also, it's usually recommended you use CompareTag instead of ==: https://answers.unity.com/questions/200820/is-comparetag-better-than-gameobjecttag-performanc.html

Create a reference to a gameobject based on a raycast hit

I want to create a reference to an instance of a game object based on if a raycast hits a specific game object. In this case, its called "resource". Once I have click the gameobject I want to create an object of type ResourceSource that holds all variables and methods of that specific gameObject.
E.g i click the gameobject. A varaible is created
ResourceSource resource = hit.collider.gameObject.GetComponent<ResourceSource>();
Obviously, I cant just create a new object as that will just be a copy so if I make any changes to the gameobject the original won't be affected.
ResourceSource class
public class ResourceSource : MonoBehaviour
{
public ResourceType type;
public int quantity;
public UnityEvent onQuantityChange;
Cooldown cooldown;
public Vector3 GetPositon()
{
return gameObject.transform.position;
}
}
The method i want to create the reference
void CheckIfResource(RaycastHit hit)
{
if (hit.collider.gameObject.tag == "Resource")
{
//Want to create something like this
ResourceSource resourcePosition = hit.collider.gameObject.GetComponent<ResourceSource>();
}
}
Still somewhat new to unity so any help is appreciated :)
ResourceSource resource;
resource = hit.collider.gameObject.GetComponent<ResourceSource>();

Cant display array items in the inspector. Unity

I want to make a class array and see all these classes items in the inspector.
I have 2 scripts. 1 -set to prefab and requires MonoBehaviour to be included.
2 - script where I create the array but in the inspector, I see only Element0, Element1...
When I remove MonoBehaviour from the 1st script I'm able to see all the items in the inspector, but that way it doesn't work with the prefab...
1-
[System.Serializable]
public class LevelSetup : MonoBehaviour
{
public TextMeshProUGUI levelName;
public Image levelImage;
public bool locked;
public GameObject Description;
public string Text;
}
2-
public class LevelSpawn : MonoBehaviour
{
public LevelSetup[] levels;
Want to be displayed array with all the "LevelSetup" fields (that are public), but if I leave the MonoBehaviour and it works fine with prefab it displays array with the only Element0, Element1, etc.
Thank You!
When you put a field that inherits from MonoBehaviour the Unity's inspector expects an object that has "Behaviour", so you cannot assign the fields in the inspector because is not interpreted as a regular field.
For example, if you set a Material as a field, and you want to change the color property from the inspector.
public Material mat; //This is actually a class
In the inspector you will only be able to assign a material but you won't be able to access inside the class and change the color.

How do I pass variable from one script to another C# Unity 2D?

For example I have a variable (public static float currentLife) in script "HealthBarGUI1" and I want to use this variable in another script.
How do I pass variable from one script to another C# Unity 2D?
You could do something like this, because currentLife is more related to the player than to the gui:
class Player {
private int currentLife = 100;
public int CurrentLife {
get { return currentLife; }
set { currentLife = value; }
}
}
And your HealthBar could access the currentLife in two ways.
1) Use a public variable from type GameObject where you just drag'n'drop your Player from the Hierarchy into the new field on your script component in the inspector.
class HealthBarGUI1 {
public GameObject player;
private Player playerScript;
void Start() {
playerScript = (Player)player.GetComponent(typeof(Player));
Debug.Log(playerscript.CurrentLife);
}
}
2) The automatic way is achieved through the use of find. It's a little slower but if not used too often, it's okay.
class HealthBarGUI1 {
private Player player;
void Start() {
player = (Player)GameObject.Find("NameOfYourPlayerObject").GetComponent(typeof(Player));
Debug.Log(player.CurrentLife);
}
}
I wouldn't make the currentLife variable of your player or any other creature static. That would mean, that all instances of such an object share the same currentLife. But I guess they all have their own life value, right?
In object orientation most variables should be private, for security and simplicity reasons. They can then be made accessible trough the use of getter and setter methods.
What I meant by the top sentence, is that you also would like to group things in oop in a very natural way. The player has a life value? Write into the player class! Afterwards you can make the value accessible for other objects.
Sources:
https://www.youtube.com/watch?v=46ZjAwBF2T8
http://docs.unity3d.com/Documentation/ScriptReference/GameObject.Find.html
http://docs.unity3d.com/Documentation/ScriptReference/GameObject.GetComponent.html
You can just access it with:
HealthBarGUI1.currentLife
I'm assuming that HealthBarGUI1 is the name of your MonoBehaviour script.
If your variable is not static and the 2 scripts are located on the same GameObject you can do something like this:
gameObject.GetComponent<HealthBarGUI1>().varname;
//Drag your object that includes the HealthBarGUI1 script to yourSceondObject place in the inspector.
public GameObject yourSecondObject;
class yourScript{
//Declare your var and set it to your var from the second script.
float Name = yourSecondObject.GetComponent<HealthBarGUI1>().currentLife;
}
TRY THIS!
//Drag your object that includes the HealthBarGUI1 script to yourSceondObject place in the inspector.
public GameObject yourSecondObject;
class yourScript{
//Declare your var and set it to your var from the second script.
float Name = yourSecondObject.GetComponent<HealthBarGUI1>().currentLife;

Categories