I have a gameObject and I want to get a value from one of the scripts. How would I point to the script? At the moment I am calling the gameObject from a script named Body and I want to get the script named RightArm.
Inside your Body script you can do this, assuming that the Arm is inside the Body.
RightArm rArm = GetComponentInChildren<RightArm>();
It will look through all the Children and find the correct component you want. You can use this to find all sorts of Components, such as Rigibodies.
Assuming the RightArm is somewhere else, maybe on the floor outside the body. Then you can do this:
RightArm rArm = GameObject.Find("RightArm").GetComponent<RightArm>();
Let "RightArm" be the name of the GameObject containing the RightArm Script.
This second implementation will look through in the scene for the GameObject named "RightArm" then look at the components in that gameObject and return you the RightArm script. If there is no gameObject named "RightArm" then you will get an exception when trying to get a component of null.
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.
Looking to get an instance of this game object so I can successfully use .enabled to hide it in a scene.
PlayPortalLoginButton loginButton = gameObject.GetComponent<PlayPortalLoginButton>();
Fairly new to C# and I believe I am close to achieving my goal with the line above. What needs changed? Want to understand how to correctly do this.
Here is one way you could find a component on a GameObject in the scene, where "PortalLoginButton" is the name of the GameObject as seen in the editor:
var loginButton = GameObject.Find("PortalLoginButton");
loginButton.enabled = false;
However, GameObject.Find("...") searches the name of every GameObject in the scene, and this is not usually the best way to reference a GameObject since it is not very efficient. So make sure not to use GameObject.Find("...") or similar function calls in the Update() function because it will execute every frame and slow your game down. If the GameObject is not instantiated while the game is running, it is usually better to make a global reference to any GameObject or Component that you use in your script and then drag-and-drop the GameObject with the Component you are looking for into the field in the editor. Alternatively, you can use GameObject.Find("...") in the Start() or Awake() functions to store a reference to the GameObject that you are looking for, so that the search only happens once at the start of your game.
Here is an example of how to store the reference in global field (it will show up in the editor and you can drag-and-drop the GameObject into it). The differences between using a public field vs a private field are explained in the comments (you can decide on using public or private):
// By default, private fields are not viewable in the editor,
// but the [SerializeField] attribute, placed before
// the field declaration, allows them to be visible.
[SerializeField]
private GameObject loginButtonPrivateReference;
// If you need to access loginButton from another script,
// you can make it a public field.
// Public fields are viewable in the editor by default.
public GameObject loginButtonPublicReference;
Here is an example of how you can use GameObject.Find("...") in the Awake() function:
private GameObject loginButton;
private void Awake() {
loginButton = GameObject.Find("PortalLoginButton");
}
If you need to search for GameObjects in your scene by type or by tag name, see the GameObject documentation here for more information. Searching by type is less efficient and searching by tag is more efficient than searching by name because type searches check each component on each GameObject, and tag searches search only an organized GameObject subset.
GameObject button;
void Start() {
button = GameObject.Find ("yourButtom");
}
void SomeEvent() {
button.SetActive(false);
}
I think you have to help to you
There are several ways to get access to a gameObject in a script depending on exactly which gameObject you are trying to get.
If you are trying to access a GameObject of a behavior in the behavior script then simply using gameObject should suffice since that is the gameObject that behavior is attached to.
Accessing a script that is attached to another GameObject is where it can be tricky. For scenes such as a MainMenu, there is nothing wrong with giving it a public reference as an example:
public PlayPortalLoginButton loginButton;
void setLoginState(bool activate) {
loginButton.enabled = activate;
}
With this example you would just drag and drop the gameObject with the PlayPortalLoginButton script on your manager script, the script that would control whether it is enabled or not.
If you need a more modular approach to it for example in a gameplay scene where you are populating objects at run time the approach you can take is:
PlayPortalLoginButton loginButton;
void setLoginState(bool activate) {
if(loginButton == null)
{
loginButton = FindObjectOfType<PlayPortalLoginButton>();
}
// Requires the correct version of .net otherwise you can reuse the check above...
loginButton?.enabled = activate;
}
In the above script if you needed to gameObject of loginButton, now you can access it through loginButton.gameObject.
There are some more examples you could use and other approaches however I feel the above should suffice if for a menu.
I will also mention I am avoiding example of GameObject.Find and GameObject.FindGameObjectsWithTag as those are more prone to error. They will only work if your name or tag are correctly marked, if you rename them for any reason then your scripts will fail to find the Object, and this can cause an issue with troubleshooting.
Using FindObjectOfType, you are less likely to have an error, and if you remove that script type these scripts will populate an error indicating the script no longer exists. When refactoring, if you right click on the behaviors name and use the rename option it will automatically update references to the script throughout your code.
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 !
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.