I am new to Unity Game Development and I find the following usage in code a bit confusing.
private Transform enemy;
// Start is called before the first frame update
void Start()
{
enemy = GetComponent<Transform>();
}
According to the documentation GetComponent() is a public function. So how can this be accessed without being instantiated?
I found a similar question was asked on Unity's community but I didn't find any of the answers answering the question exactly to the point. Please help me in understanding this.
The link to question on Unity forum is below.
Question
My Unity version is 2018.4.16f1
Thanks!
Your class most probably inherits from MonoBehaviour which inherits from Behaviour which inherits from Component.
Component implements GetComponent
Fazit: The instance which you are calling this method on is no other than this, the instance Start is called on.
Btw for Transform there is already a dedicated property Component.transform so you should not use GetComponent for getting a Transform reference.
you are calling the GetComponent() method of the GameObject you added your MonoBehavior to and assign it to the Transform enemy. It is even the first Answer from your linked Question.
Related
Good evening.
So I want to assign a text box to an instantiated object but how do I go about doing this via code and not manually. As hundreds of these prefabs could be instantiated I need to be able to assign the text box in the inspector via code at runtime (As in when they are created).
Just to note: all these fields are assigned on the object that this prefab is a clone of, just for some reason the scripts copy over but the assigned values don't?
Let me know if you need to see any code but I think the question explains enough.
Thank you in advance!
https://gamedev.stackexchange.com/questions/135209/how-to-store-references-to-scene-objects-in-prefabs - This post answers my question. (It is a set of ways to assgn variabkes to prefabs in the inspector).
I thought I might as well repost it here as the answer is on a different forum.
GameObject bullet = Instantiate(bulletPrefab, transform.position, transform.rotation);
bullet.GetComponent<BulletScript>().shooter = gameObject;
Seems to be the best way to do it, using GetComponent to decidd what script you want to assign something to and then assigning that part using .variable = whatever you want it to be.
I'm using the Method FindObjectsOfType inside Unity and I want to know what the order Unity find objects?
I tried to change the order of my game objects inside the hierarchy and even change the name of my game objects to 1_name, 2_otherName and still the list seems random.
Do it really random or there is an order for the search? There is no documentation about the order in the Unity website.
If someone really want, this is my relevent script:
[SerializeField] List<AreaMeshHandler> areaMeshHandlers;
void Awake()
{
areaMeshHandlers = FindObjectsOfType<AreaMeshHandler>(true).ToList();
}
Short answer, by InstanceID. can be seen on each GameObject in debug mode.
Tested by running this code in a scene with multiple GameObjects (some in hierarchy)
foreach (Target t in FindObjectsOfType<Target>())
Debug.Log($"{t.name}: {t.GetInstanceID()}");
I'm currently developing a game in Unity using C# and I've run into a small problem.
I need to spawn a certain gameobjects relative to the Spawnposition and length of another game object. Now I figured that bounds.size would be the best function to use in this instance. As shown bellow I declare first the variable that uses this in my start method:
public void Start()
{
GameObject PointBar = (GameObject) Resources.Load("PointBar Horizontal");
PointBarVectorLength = PointBar.GetComponent<BoxCollider2D>().bounds.size.x;
PointBarVectorConv = Camera.main.WorldToViewportPoint(new Vector2(PointBarVectorLength, 0f));
}
However, the gameobjects in question are inactive at start's call and thus I presume don't return any value for bounds.size when called.
Does anyone know how I can access the bounds.size or equivalent of an inactive gameobject or is there something else I'm missing here?
As noted in the documentation for the Collider.bounds property, bounds "will be an empty bounding box if the collider is disabled or the game object is inactive". So your assumption was pretty much right. Since the object doesn't exist in worldspace that makes sense.
I'm not sure about the most elegant solution for your use case but two options spring to mind.
Calculate the object's spawn dimensions by accessing its transform.localScale and factoring in the scale of prospective parent objects. That could get messy but you could probably also write a helper method to make it more manageable.
Instantiate the object somewhere off screen after you load it, access its Collider.bounds property to get the information you need then move it where ever you want it or store the information for later.
There may be better solutions but that's what leaps to mind for me.
I solved the issue by using GetComponent().bounds.size.x;
instead of BoxCollider. This component can get accessed when the game object is not active.
I am trying to call a function in another c# script, that is attatched to another gameObject in my scene. I am creating an instance of the script LevelChanger in the Grounded one like this:
LevelChanger levelChanger;
Then, in the Awake() function:
GameObject gameObject = new GameObject("LevelChanger");
levelChanger = gameObject.AddComponent<LevelChanger>();
then calling like this in an IEnumerator:
levelChanger.FadeOut(true); // line 178
Then this is the LevelChanger class:
using System.Collections;
using UnityEngine;
public class LevelChanger : MonoBehaviour
{
public Animator animator;
public void FadeOut(bool fadeIn)
{
animator.SetBool("Fade", true); // line 10
if (fadeIn) StartCoroutine(FadeInAsWell());
}
IEnumerator FadeInAsWell()
{
yield return new WaitForSeconds(0.9f);
animator.SetBool("Fade", false);
}
}
I've been trying to solve this problem for quite a while now, I checked everywhere (here, here, here, here and on other sites). I saw that because my LevelChanger script is attatched to a gameobject, so it is MonoBehaviour, it is not possible to create an instance of the class from another script, like this:
LevelChanger levelChanger = new LevelChanger();
or either "normally" like I was doing at first like this:
LevelChanger levelChanger;
Then just calling its functions like
levelChanger.FadeOut(true);
Most of the time I was getting a NullReferenceException at runtime (at line 176), now directly in the LevelChanger script (at line 10).
At this moment, I truly have no idea how to fix this: does anybody know how?
(I'm still a beginner).
Thanks in advance!
Based on the conversation we've had in comments, I'll write an answer here to be more thorough.
So, let's recap. What you want to do is call a function from LevelChanger. But, you are unsure of how to get a reference to LevelChanger. This is the core problem every programmer faces: How do i get that stuff over there, and what's the best way to do?
Based on what you've said, your prefab exists in the scene, so you want to grab a reference to it.
One simple, lazy way is to call FindObjectOfType<LevelChanger>. This will search through the entire scene for components of that type, and will return your LevelChanger instance. I don't recommend this because it's pretty lazy and inefficient. This is only needed if one or both of your objects exist at run-time but not at edit-time
Another way is to treat LevelChanger like a singleton.
add a public static LevelChanger Instance; field to your LevelChanger. Then, on Awake() set Instance to this. ie Instance = this;
public static LevelChanger Instance;
public void Awake()
{
Instance = this;
}
Then, in any other script, you can call LevelChanger.FadeOut(false);
This is a similarly lazy way, but not quite inefficient. It does make your code a little harder to follow and there are a lot of devs that have problems with static instances like this. Just so you know.
One other way is to create an instance of the prefab using GameObject.Instantiate() and calling the function after getting a reference to the component. This is a bit more involved, but it might be a cleaner way for you.
There are two ways to do this, so lets do the cleanest way. In your project, create a folder called Resources if you don't already have one. Resources is a name unity will specifically look for when calling Resources.Load(). Drag your prefab object into that folder to create a new prefab. Call it LevelChanger
//Spawn the prefab gameobject
GameObject gameObject = GameObject.Instantiate(Resources.Load("LevelChanger")) as GameObject;
//Get a reference to its component LevelChanger
LevelChanger levelChanger = gameObject.GetComponent<LevelChanger>();
//Call the function
levelChanger.FadeOut(false);
After your prefab finishes the fade, you can have it destroy itself via Destroy(gameObject);
Finally, since you've indicated both scripts exist at edit time, you can simply add an inspector reference. This is the easiest way, but don't go crazy with inspector references. It makes the code difficult to follow.
public LevelChanger levelChanger;
Quick and dirty because little has been shared about the code and scene in question.
In Awake, get a reference to the gameObject with the already existing LevelChanger on it:
GameObject levelChangerGO = GameObject.Find("LevelChanger");
levelChanger = levelChangerGO.GetComponent<LevelChanger>();
then calling like this in an IEnumerator:
levelChanger.FadeOut(true); // line 178
As per the title, I'm essentially looking for a way to associate a Prefab with a script that doesn't implement MonoBehaviour. From the Unity editor, I can normally drag a Prefab and drop it directly into the script, but as soon as I remove MonoBehaviour, I no longer have the option to. I need to remove MonoBehaviour because I'm creating instances of the class that I can pass onto a "manager".
I've seen plenty of examples of people referencing a Prefab through a script through code at runtime, but that seems unnecessary since I'm never going to change the prefab I'm associating with that particular variable, and I have the prefab object ready before any code is actually run. I'm leaning towards Resources.Load() as my answer, but I'm not exactly sure whether that's the ideal thing to do.
Is there any trick to specifying a Prefab before runtime, or what's the most efficient way to associate a GameObject variable with a Prefab in a way similar to the "drag and drop" method of association in the Unity Editor?
You can have your normal C# class point to a GameObject or a prefab.
using UnityEngine;
public class NotMonoBehaviour
{
private GameObject gObject;
public NotMonoBehaviour()
{
gObject = Resources.Load("MyPrefab") as GameObject;
}
}
In this case the code goes into the Resources folder and finds the Prefab.