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.
Related
Using Unity. When instantiating a new gameObjectA with ScriptA, I access gameObjectB's script (ScriptB) while doing so. The thing is, I can only use the prefab of gameObjectB, instead of an already instantiated gameObjectB. For example -
public class ScriptA : MonoBehaviour
{
public ScriptB scrptB;
void Start()
{
float X = scrptB.IntegerThatIncreasesEveryFrame;
Debug.Log(X);
}
In every frame that a gameObjectB has been instantiated, I have integer IntegerThatIncreasesEveryFrame (I'll call it ITIEF now) that, of course, adds 1 to itself every frame.
When gameObjectA and ScriptA gets instantiated, I want to use gameObjectB's ScriptB's ITIEF (e.g. 100 after 100 frames after being instantiated).
I have to use a prefab of gameObjectB, though. When gameObjectA gets instantiated, it uses the DEFAULT value of ITIEF (which is zero).
If this makes sense please help!
In order to access the information from an instanced object, you need to have a reference to the object. In your case, you are referencing the prefab, not the instanced one in game.
The reason why you cannot drag the script itself into the Inspector is because a reference needs to reference a script that is instanced. ScriptA cannot make a reference to ScriptB unless ScriptB is instanced into a gameobject. A prefab acts as an instanced object that doesn't 'exist' in the game. If you want a reference to the instanced script that IS in the game, then you need to set the ScriptB variable to be that in-game script.
ScriptB instance = GameObject.FindObjectObType<ScriptB>();
This line finds the first instanced form of ScriptB.
This only works if there is ONE instance of ScriptB in the game. If there are more, you need to do a more complicated bit of code.
Are there the same amount of ScriptA and ScriptB? Then when they are both first instanced, store ScriptB somewhere, and then update ScriptA with it.
Your question leaves a lot more questions, but I think I've covered most of the solutions. Pretty much, if you have more than one ScriptB instance, then store the one you want to use and then set it on the ScriptA instance. Otherwise, use FindObjectOfType to get a single instance.
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 !
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've tried multiple ways of initializing the object, and the thing just wont work. I think the problem may lie in one of my other classes, so I've put all the important ones in pastebin.
THE CLASS THROWING THE ERROR: http://pastebin.com/Pj04kUbj
THE TYPE CLASS OF THE OBJECT THROWING THE ERROR:
public class PlayerCharacter : BaseCharacter {
}
THE SUPERCLASS OF THE OBJECT: http://pastebin.com/GAmSMXbh
(damn thing wont let me post more than 2 links)
I doubt this will be solved here, as this is kind of a massive infodump, but if its something really simple and you guys catch it that would be awesome. In the meantime, ill keep looking, but im having little luck
You cannot create a GameObject in that way:
If you use new operator to create PlayerCharacter, you will not have a Unity GameObject at the end. You must Instantiate from a prefab or clone from another GameObject.
On the other hand, you cannot call Awake directly because the Unity GameObject is not built. This function is called from Unity when the GameObject is built for its first time.
See here for an example of creating GameObjects.
EDIT:
you must add the script component to your PlayerCharacter like this:
_toon.AddComponent( PlayerCharacter ) as PlayerCharacter
in that way the script is attached to your GameObject because using new to create it, the script is not attached.