Instantiated prefab should call a function from the main script? - c#

I want something like this.
ComponentTest.cs - This script is attached to a empty game object in the scene.
public class ComponentTest : MonoBehaviour {
public GameObject boxPrefab;
void Start () {
GameObject temp = Instantiate(boxPrefab, new Vector3(0,0,0), Quaternion.identity) as GameObject;
temp.GetComponent<PrefabBox> ().go = gameObject.GetComponent<ComponentTest>().Yes();
}
public void Yes(){
print("yes");
}
}
and PrefabBox.cs - This script is attached to the prefab.
public class PrefabBox : MonoBehaviour {
public GameObject go;
void Start () {
go ();
}
}
I get this as error:
The member `PrefabBox.go' cannot be used as method or delegate

First of all, the go object is declared as a GameObject but then you assign a function to it and then call it like a function.
It looks like you want Closures in which you can store functions to variables and call them in the way you do.
This post covers it: http://answers.unity3d.com/questions/494640/capturing-a-variable-in-a-closure-behaves-differen.html
Seems the data type needs to be Action but best to read up on it to grasp it properly.
Good luck.

Related

Unity: How to destroy an Instantiated object in a different function

I'm trying to make a game which is spawning an object and after the object is destroyed, another object spawns right away. But right now I'm trying to destroy an instantiate object in a different function, and it is not working.
`
public GameObject[] food;
public Vector3Int spawnPosition;
public void Start()
{
SpawnFood();
}
//Spawning food
public void SpawnFood()
{
int random = Random.Range(0, food.Length);
GameObject clone = (GameObject)Instantiate(food[random], this.spawnPosition, Quaternion.identity);
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.C))
{
Destroy(this.gameObject);
}
}
`
I have tried to do some research on this and still, I can only find the solution for destroying an object inside the same function as the Instantiate.
When you call Destroy(this.gameObject), the game object the script attacting to will be destroyed, and after that you cannot call the script.
I guess what you want to destroy is the food game object, not the game object the script you showed here attacting to.
A quick adjustment to suit your need maybe :
...
private GameObject clone
...
private void Update()
{
if(Input.GetKeyDown(KeyCode.C))
{
if (clone != null)
Destroy(clone);
}
}
And as #Daniel seggested, if you will repeatedly instantiate/destroy food game object, the better way would be just use the same food object and change it's properties (e.g. location...) to create the new food game object pop-up illusion.
The key idea here is called Object Pooling.
Here is your answer :
declare a public Gameobject:
public GameObject clone;
and replace
GameObject clone = (GameObject)Instantiate(food[random], this.spawnPosition, Quaternion.identity);
with
GameObject clone = Instantiate(food[random], this.spawnPosition, Quaternion.identity);
and then you can destroy in another function or class
public void DestroyFood()
{
Destroy(clone);
//you can instantiate another gameobject here
}

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
}
}

Variables in script do not show in Inspector (Unity)

I'm trying to learn how to use Unity and following online tutorials but I am currently having a problem that I don't understand how to fix.
I have a Sprite in my scene and I have attached a script to it however in the Inspector it shows the script is there but I cannot see the variables inside? I had this problem previously and it sorted itself out.
What is the cause of this problem/how do I fix it?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpaceShip : MonoBehaviour {
public float speed = 30;
public GameObject theBullet;
private void FixedUpdate()
{
float horzMove = Input.GetAxisRaw("Horizontal");
GetComponent<Rigidbody2D>().velocity = new Vector2(horzMove, 0) *
speed;
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Jump"))
{
Instantiate(theBullet, transform.position, Quaternion.identity);
}
}
}
Edit: The problem was solved by reimporting.
You either need to declare the variables as Public or [SerializeField] for member variables to appear in the inspector. Note that by declaring something as public allows access to the variable from outside the class (from other scripts/classes for example). By default, private is assigned to member variables.
Example:
public class testscript : MonoBehaviour
{
public int foo; // shows up in inspector
[SerializeField] private int bar; // also shows up while still being private
void Start()
{
}
}
Not is a problem, You forget to do something surely.
It is common at first with Unity.
Start again.
In the scene create a new GameObject and add you script.
If the inspector shows not variable:
The varible do not is public (false, if is public in you script)
There is some syntax error in the script!
or
You were not adding the correct script to the GameObject.
There are not many secrets to that, if all is well enough that the variable is public and this outside of a method of the script so that it is seen in the inspector.
One tip, do not use a GetComponent or Instantiate inside a FixedUpdate or Update because they are expensive, save the Rigidbody2D in a variable in the Start and then use it.
Sorry for my English and good luck.

How to call a public static variable from another class, change its value and then check that its changed from its original class [duplicate]

So im trying to change a variable in another script by touching a cube.
Current setup
1x Player
1x Enemy
Each with their own script Enemy_Stats & Character_Stats
As you can see in this little snippet it's quite a workaround to access the variable from another script.
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Enemy")
{
collision.gameObject.GetComponent<Enemy_Stats>().Health =
collision.gameObject.GetComponent<Enemy_Stats>().Health
- gameObject.GetComponent<Character_Stats>().AttackDamage;
if (collision.gameObject.GetComponent<Enemy_Stats>().Health <= 0)
{
Destroy(collision.gameObject);
}
}
}
Iam new to Unity, but isn't there a way to just refer it with something like:
collision.Health?
How to access variables/functions from another Class. The variable or function you want to access or called must be public not private.
public class ScriptA : MonoBehaviour{
public int playerScore = 0;
void Start()
{
}
public void doSomething()
{
}
}
Access variable playerScore in ScriptA from ScriptB. First, find the GameObject that the script or component is attached to with the GameObject.Find function then use the GetComponent function to retrieve that script or component that is attached to it.
public class ScriptB : MonoBehaviour{
ScriptA scriptInstance = null;
void Start()
{
GameObject tempObj = GameObject.Find("NameOfGameObjectScriptAIsAttachedTo");
scriptInstance = tempObj.GetComponent<ScriptA>();
//Access playerScore variable from ScriptA
scriptInstance.playerScore = 5;
//Call doSomething() function from ScriptA
scriptInstance.doSomething();
}
}
No since Health is not part of the collision object, but Enemy_Stats. You can cache a Component (that's what Enemy_Stats is) if you use it multiple times to save you some typing (and some performance, but that is rather marginal for this example). Also you can cache "known" components like in this case Player_Stats. You can do this e.g. in Start or with a public variable and the inspector.
What you should probably do though is to make the enemy be responsible for his life and not the player, so move the Destroy-part to Enemy_Stats (into the Health property to be exact).
The first thing to make this shorter (and eventually faster) would be to store this: gameObject.GetComponent<Character_Stats>() on Start() in a private variable (you should avoid calling GetComponent on a frequent basis if you can avoid it).
For the Health variable, a way of avoiding GetComponent calls could be caching: you create a Dictionary<GameObject, Enemy_Stats> and read from that as soon as this gameobject collided once
At the very beginning i mean in Awake() method you can find a game-object with tag
and get it's Heath after that in Collision() method you should just decrease the health but, here the condition is there is only one enemy and only one player.

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