Create a reference to a gameobject based on a raycast hit - c#

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>();

Related

How can I make a static gameObject variable and show it in the inspector in order to assing the gameobject that I want?

I basically want to make a public static gameObject but it doesnt show it in the inspector.How can I assign the gameobject I want then?
Static cannot be shown in component instance because it is "above" the component, it belongs to the class type and there is only one shared by all components of this type.
Your solution could be to find the game object and then assign it to the static variable.
public static GameObject TheStaticGO {get; private set;}
void Start()
{
// Only assign if empty
if(TheStaticGO == null){
TheStaticGo = GameObject.Find("StaticGOName");
}
}

Assign gameObject of a script via another script?

How do I assign a gameObject of one script through another script's gameObject? For example;
Script_1
public class Script_1 : MonoBehaviour
{
public OVRScript OVR;
}
Script_2
public class Script_2 : MonoBehaviour
{
private Script_1 src_1;
public GameObject Front;
void Start()
{
src_1 = (Script_1) GameObject.FindObjectOfType(typeof(Script_1));
src_1.GetComponent<OVRScript >().OVR = Front //I am facing problem here
}
}
Both GameObjects "OVR" and "Front" contain the OVRScript
src_1.GetComponent<OVRScript>().OVR = Front.GetComponent<OVRScript>().OVR;
I don't know or see the OVRScript class but isn't OVR rather a member of Script_1?
And then you would want to use GetComponent on the Front in order to get a component attached to it.
// If possible rather drag your Script_1 in here directly via the Inspector
[SeializeField] private Script_1 src_1;
void Start()
{
// Now I would use find only as fallback
if(!scr_1) src_1 = GameObject.FindObjectOfType<Script_1>();
// then you want to assign the OVR field of the 'src_1' of type 'Script_1'
// and not use 'src_1.GetComponent<OVRScript>()' which would return
// the reference of an 'OVRScript' component attached to the same GameObject as the Script_1
//
// And you want to fill it with the reference of an 'OVRScript' attached to 'Front'
src_1.OVR = Front.GetComponent<OVRScript>();
}
(see [SerializeField])
It would be even better if you directly define
public OVRScript Front;
now if you drag in a GameObject it a) is checked if this GameObject actually has a OVRScript attached, otherwise you can't drop it and b) instead of the GameObject reference already the OVRScript reference is serialized and stored so there is no need for GetComponent anymore:
[SeializeField] private Script_1 src_1;
public OVRScript Front;
void Start()
{
// Now I would use find only as fallback
if(!scr_1) src_1 = GameObject.FindObjectOfType<Script_1>();
src_1.OVR = Front;
}

Passing values from one script to another without a game object in the scene

I’ve found a lot of information on passing parameters from one script to another when a game object is present in the hierarchy. My problem is that my Transform object is created on the fly using Instantiate(myPrefab). Is there any way to access the position of myPrefab game object from another script?
You could store a reference to the instantiated GameObject after it has been instantiated (see example below). If there are more GameObjects, use a list to store them instead.
Call the InstantiateGO() and GetGOPosition() where it makes sense for you.
public class YourClass: MonoBehaviour
{
public GameObject yourPrefab;
public GameObject yourGameObject;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
void InstantiateGO()
{
yourGameObject = Instantiate(yourPrefab); // assign the newly instantiated GameObject to yourGameObject
}
void GetGOPosition()
{
var x = yourGameObject.position;
//Do something here
}
}

How i can destroy an GameObject but also store the gameobject in a variable

When i pick a item in my scene, it calls the AddItem() method, and this method would add the item to an List and destroy the gameObject from the scene, but when i try to acess the gameobject in the list this error appears.
"MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it."
public class Inventory : MonoBehaviour
{
public List<GameObject> itemsGOInInventory = new List<GameObject>();
public void AddItem(GameObject itemToBeAdded)
{
itemsGOInInventory.Add(itemToBeAdded);
Destroy(itemToBeAdded);
}
public void FindItem(string name)
{
foreach (GameObject item in itemsGOInInventory)
{
if (item.GetComponent<Item>().itemName == "pistol")
{
Instantiate(item.GetComponent<Item>().itemObject, this.transform);
}
}
}
}
Once you destroy the gameobject, its gone.
What you can do is hold a reference to that object and then store it somewhere and make it invisible. Its called object pooling.
Unity has a tutorial on this here: https://unity3d.com/learn/tutorials/topics/scripting/object-pooling
You need to set the gameobject SetActive to false or use other means to make it invisible.
https://docs.unity3d.com/ScriptReference/GameObject.SetActive.html
You already have the list of objects, so instead of Destroy(), use SetActive(false);
itemToBeAdded.SetActive(false);
Hope this helps.
You say that you destroy GameObject once its picked up. Once destroyed, it doesn't exist and all references to the GameObject are null. It is a bad idea to keep list of gameobjects in your case. Instead, you should have a model class for inventory items.
public class InventoryItem
{
string name;
string description;
string spritePath;
// other variables
}
You should create a separate class to represent the InventoryItem in the scene. You could have something like this on your gameobjects:
public class InventoryItemView : MonoBehaviour
{
public InventoryItem item;
// ...
}
Now put the item script on 'items' in your scene. Whenever you pick an item, get the InventoryItem script from the gameobject and add it to the list of InventoryItems in your Inventory. Then destroy the gameobject. Now even when your gameobject is destroyed, you have your InventoryItem object.
public class Inventory : MonoBehaviour
{
public List<InventoryItem> itemsGOInInventory = new List<InventoryItem>();
public void AddItem(GameObject itemToBeAdded)
{
itemsGOInInventory.Add(itemToBeAdded.GetComponent<InventoryItemView>().item);
Destroy(itemToBeAdded);
}
//...
}
You might want to check for whether the GameObject has the InventoryItemView script on it.
Ideally your inventory class should not be MonoBehaviour, a serializable class would have sufficed, but that is off topic.

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