void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Instantiate(Resources.Load("Objects/Level"), transform.position, Quaternion.identity);
}
}
This is my code. I have an object named Level.obj inside of a folder named "Objects" inside of my Assets. I attempt to spawn it on top of the parent object of this script with Resources.Load("Object/Level"). I believe this code itself is correct because the console returns with "The Object you want to instantiate is null." upon pressing the spacebar. What's probably wrong is my parameters, specifically how I attempted to find the object. I have also tried Assets/Objects/Level as opposed to what's above.
Add a public field public GameObject myPrefab; to your monobehavior.
Set it in the editor by selecting your gameobject and using the inspector.
Instantiate it like Instantiate(myPrefab, transform.position, Quaternion.identity);
You only need Resources.Load if your asset doesn't exist at compile time. And like the documentation says, Resources.Load needs the asset to be in the Resources folder.
https://docs.unity3d.com/ScriptReference/Resources.Load.html
I never used Resources.Load() so you may try to achieve something different, but what I do to "spawn" objects is to make them into a prefab (just drag/drop your object to your assets). Then declare a public GameObject field on your script, drag/drop the prefab in it in the inspector and then Instantiate it like you did.
Hope it helped !
Related
EDIT: I found the problem. I am simply a big dumb!
I removed "public static" from "IEnumerator" and that fixed everything.
I am a COMPLETE beginner to programming, and this is the first program I have ever written. To learn, I decided to remake simple games and Flappy Bird was my first attempt.
my problem: I declared a gameobject with "[SerializeField] GameObject" but cannot assign the prefab in the inspector.
This script "SpawnPipes" is attached to an empty gameobject "PipeSpawner"
[SerializeField] public GameObject Pipe;
//declared some other variables and stuff..
void Start()
{
StartCoroutine(SpawnRoutine());
}
public static IEnumerator SpawnRoutine()
{
while (spawningOn == true)
{
Instantiate(Pipe,
new Vector3(xpos, UnityEngine.Random.Range(minYPos, maxYPos), 0), Quaternion.identity);
Debug.Log("spawned a pipe");
yield return new WaitForSeconds(spawnRate);
}
}
As you can see, I have declared a gameobject "Pipe" which is serialized, and so should show up in the inspector. And it did... at first.
I was doing some final bug fixing, when suddenly this code broke. I was editing a different script (which includes code that turns "spawningOn" to true or false depending on the gamestate) and when I tested it, a new error showed up my SpawnPipes script, which I hadn't even touched!
Here is the error message:
An object reference is required for the non-static field, method, or property 'SpawnPipes.Pipe'
The error refers me to the line
Instantiate (Pipe,
When I hover over "Pipe," is highlights my "GameObject Pipe;" so I know it's properly relating the two. But it seems to think I do not have a prefab assigned, which I did.
The first thing I tried was changing my "GameObject Pipe" to "static GameObject Pipe". This removed the error, but when I tested the game the pipes did not spawn and I got the message that the object I was trying to instantiate was null, as in there was no object assigned to "GameObject Pipe" ..
I opened my gameobject "PipeSpawner" in the inspector, and looked at the "SpawnPipes" script, and for some reason, my Pipe field was gone. Remember, I declared my GameObject Pipe as both serialized AND public, so there is no reason it should be missing!
I erased the GameObject declaration code and rewrote it with and without "static", the field did not return. I reimported all of my prefabs, the field did not return. I relaunched Visual Studios and Unity, the field did not return.
Eventually, I do not remember what did it, but I did get the field to come back and I assigned my pipe prefab to it once again.
However, it STILL says
An object reference is required for the non-static field, method, or property 'SpawnPipes.Pipe'
The prefab is assigned!! Only one field is named "Pipe" so I know it is assigned to the right field!! Please help!
[SerializeField] public GameObject Pipe;
is non-static field that means that static functions can't access it, consider to turn the function to non-static
public IEnumerator SpawnRoutine()
in this case you won't be able to call the function directly you need an instance of the class, you could use singleton to call the function.
It sounds like you needed to add the script component to the gameObject and then, in the inspector with the gameObject selected, scroll down to the script and drag the gameObject into the empty bar where it goes. I could be wrong, because I'm not looking at your interface on Unity, but it sounds like maybe you need to do that.
Being a student and having finished my school year I studied the development of Unity in C # to learn how to use the engine but also and above all to have fun.
One of the advantages of Unity is that you can pass a game object parameter directly in drag/drop, but for this to be possible it is necessary that the said variable is in public, which goes against what I have learned in class (the attributes must be private as often as possible).
My question was, how to make sure to have the same result with private attributes, i.e., recovered the game object manually without using the drag/drop system?
Thanks in advance and sorry for my English level.
It is not necessary to mark the variable as public in order to make it appear in the Editor. Just just put the SerializeField attribute on top of the private variable and it should show up in the Editor.
[SerializeField]
private GameObject cam1;
You can also do the opposite which is make public variable not show in the Editor. This can be done with the HideInInspector attribute.
[HideInInspector]
public GameObject cam1;
But there is another method in Unity to get a GameObject, by avoiding
drag/drop ?
Yes. Many ways.
If the GameObject already exist in the scene then You can with one of the GameObject.FindXXX functions such as GameObject.Find, GameObject.FindGameObjectWithTag
For example,
[HideInInspector]
public GameObject cam1;
// Use this for initialization
void Start()
{
cam1 = GameObject.Find("Name of GameObject");
}
If the GameObject is just a prefab then put the prefab in a folder named Resources then use Resources.Load to load it. See this for more thorough examples.
Finally if you just want to get the component of that GameObject, just like your cam1 variable which is not a GameObject but a component, First, find the GameObject like I did above then use the GetComponent function to get the component from it.
private Camera cam1;
// Use this for initialization
void Start()
{
GameObject obj = GameObject.Find("Main Camera");
cam1 = obj.GetComponent<Camera>();
}
Like in here, but the difference is that it's supposed to be done from an instantiated prefab, so I can not drag the GameObject, that has the script with the variable I want to access, into this script.
This was working
public ScriptA script;
void Update() {
if (script.varX < 0) {
// . . .
}
}
But now I'm getting "Object reference not set to an instance of an object" error, which I think comes from the fact that the script trying to access ScriptA, is attached to an instantiated prefab.
How do I attach scripts and/or GameObjects at runtime?
Looks like you need to find your script type first, if it already exists in the scene:
public ScriptA script;
void Start()
{
script = GameObject.FindObjectOfType<ScriptA>();
}
void Update()
{
if(script.variable...)
}
You want to use AddComponent, like:
ScriptA script = gameObject.AddComponent<ScriptA>() as ScriptA;
See the docs here:
https://docs.unity3d.com/ScriptReference/GameObject.AddComponent.html
Best way to satify the links is fill the fields in the very next lines after you instantiate, that way you can avoid ugly and expenstive Find* calls (I am assuming the script that does the instancing can be made aware of what the target objects are, after all it knows what and where to instantiate)
Its worth noting that newly instantiated scripts' Awake() method will be called before Instantiate() returns, while its Start() will be called at the start of following frame, this is a major difference between the two calls, so if your instantiated script needs the refectences in Awake() you should either refactor (move stuff to Start()) or use Find* as suggested earlier.
I am trying to instantiate a coin prefab that appears when an enemy dies.
To initially get a reference to the prefab, I retrieved it using its tag:
private GameObject coinSpawn;
Start(){
coinSpawn = GameObject.FindGameObjectWithTag("xxx");
}
Now when the enemy dies, I call Instantiate() as follows:
Instantiate(coinSpawn, transform.position, Quaternion.identity);
However, when I was playing the game and an enemy died, nothing was spawned and I got this error:
ArgumentException: The Object you want to instantiate is null.
I do not understand what I did wrong - I confirmed that I have properly tagged the prefab which I want to instantiate.
One more thing is that I want to do this without making a Resources folder. Is that possible?
Unfortunately, GameObject.FindGameObjectWithTag() only retrieves active GameObjects with the given tag that already exist in the current scene. It sounds like you're trying to use this method to retrieve a reference to a prefab object in your Assets folder, which is something it can't do. As a result, the method is returning null and assigning it to coinSpawn, leading to the error when you try to use coinSpawn later.
You likely need the Resources.Load() method, to which you can supply a path to an object in your Assets folder. Just use that in place of GameObject.FindGameObjectWithTag():
private GameObject coinSpawn;
Start(){
coinSpawn = Resources.Load("path_to_prefab") as GameObject;
}
And yes - you will have to use the name of the prefab instead of its tag to identify it, but I don't think that should pose any problems. (If it does, please update your question accordingly with an explanation.)
Hope this helps! Let me know if you have any questions.
I have a Projectile Script attached to a GameObject. Now i want to access the LinearProjectile() method in Projectile Script from Script A attached to GameObject A. Here i made a public field of type Projectile in Script A and passed in one GameObject where Projectile Script is attached.
To access LinearProjectile() method i just did.
projectile.LinearProjectile(transform.position, transform.rotation, this.direction, this.shotPower);
//Here is my method defination..
public void LinearProjectile(Vector3 position, Quaternion rotation, Vector2 direction, float force)
{
Debug.Log("called");
this.direction = direction;
this.force = force;
this.projectileType = ProjectileType.Linear;
}
All the field value assigned in this method are in default state since this method is never called. How can I access this method from other GameObject Script.
I tried GetComponent().method() but even though i can't acess what is the error here? i spent alot of time to find out but no success.. Help me out
Provided a scenario like this:
We have a GameObject in scene, let's call it Item
We have ProjectileScript attached to Item
We have a A script attached to Item
All we need to do is to call inside A script:
gameObject.GetComponent<ProjectileScript>().LinearProjectile();
If it's on another GameObject, I would personally create field in script A to be used in Inspector, for example: public GameObject ProjectileScriptHolder and then just drag GameObject from scene that holds ProjectileScript into that variable in Inspector and the access it that way:
ProjectileScriptHolder.GetComponent<ProjectileScript>().LinearProjectile();
I would also check every GetComponent<T> before calling method as it might return null, ie:
ProjectileScript script = ProjectileScriptHolder.GetComponent<ProjectileScript>();
if (script != null)
script.LinearProjectile();
If you can't attach item through Inspector, you can use FindWithTag() and find GameObject in scene provided it has proper Tag attached. FindWithTag() takes string as parameter and will look for GameObject with such tag in scene.
I understand that you want to access a script from another script on another gameobject!
Way 1
There is a simple way to do that, caching the script. (Assuming the name of the script is: "ProjectileScript")
On ScriptA you create a
public ProjectileScript pS;
and you need to initialise it, there is two ways:
1- on the inspector of GameObjectA, drag the GameObject with the projectileScript.
or
2.1- if the script is in the same game object:
pS = GetComponent<ProjectileScript> ();
2.2- if it is on another gameobject you might need to find this object somehow. Consider using a tag
pS = GameObject.FindGameObjectWithTag("projectile").GetComponent<"ProjectileScript">();
And cast it inside Script A:
pS.LinearProjectile();
Way 2
Or you can make a generic tag on the GameObject with the ProjectileScript and find it that way:
GameObject.FindGameObjectWithTag("projectile").GetComponent<"ProjectileScript">.LinearProjectile();
This make sense for you? Sorry my english.