I'm new to Unity. I have an invisible GameObject , call it A, with only a script, that instantiates a prefab B multiple times. I need spawned clones of B to have reference back to A, I have learned that in order for this to work, A has to be a prefab itself (correct me if I'm wrong) Spawned B objects react to mouse clicks and call a method of A. The problem is that inside this called method of A, the variables of A itself have values that I don't expect, for example a certain variable that was initialized to 0 in Start() and never used has a value of 12. It seems like every spawned object B has a reference to its "own" A, and variables of A have random values. What am I missing?
in order for this to work, A has to be a prefab itself (correct me if I'm wrong)
I assume that you are setting the relevant field in the script on prefab B to the prefab of A, which is not what you want. A doesn't have to be a prefab at all.
A prefab is a serialized GameObject that contains specific shared default values for easy GameObject management through the Editor and Editor/in-game scripts. A prefab is used when dealing with a large number of similar objects; each prefab instance will be similar to another with the exception of a few modified properties. This allows for large scale instantiation modification of prefab instances in a single click. For example, storing a gun projectile object as a prefab allows you to modify the default size of all gun projectiles with a single click, while allowing for property customization on a per-instance basis. You can think of prefabs as templates you can use to instantiate a GameObject.
When spawning an instance of prefab B through the script on A (henceforth referred to as ScriptA), simply set the required field on the script on the spawned instance of B (hereafter referred to as ScriptB) to the gameObject (or some other) field of ScriptA, like the following:
// ScriptA's method which spawns instances of prefab B
GameObject bInstance = Instantiate(prefabB);
ScriptB scriptOnBInstance = bInstance.GetComponent<ScriptB>();
scriptOnBInstance.referenceToAGameObject = this.gameObject;
Related
I have an animator component on one object and I have to access it in one of my scripts. But I do not know how to do it. Of course, it could be done via SerializeField, but I can't do that, since I can't select the animator of another prefab for my current prefab (since it's not visible to it). So it remains to do this only through code, if possible. The access modifier for the animator has already been configured (public).
I assume you have a GameObject A with an animator component, and a GameObject B with a custom script that needs a reference to an animator component.
If both are in the scene, or if A is a prefab:
Select GameObject B, then drag GameObject A into the reference slot of your custom script. If A is a prefab you can call Instantiate(animatorOnA) and it will return a reference to the animator on the newly instantiated object.
If both are instantiated in the same script, you can use GetComponent() on the instantiated copy of A's prefab to get a reference to the animator. Then you can assign the animatorOnA field on B using this reference.
If A is a child of B then you can assign it directly in the inspector, and it will automatically update the reference.
So I assume at one point you instantiate the prefabs in the scene, I don't know which one you instantiate first but you could do this in the script that instantiates those prefabs like this:
// The instantiate function will return the object you instantiated so you can store that in a variable
var prefabWithTheAnimator = Instantiate(yourPrefabWithAnimator);
var prefabThatNeedsTheAnimator = Instantiate(yourOtherPrefab);
// Now you can get the animator of the prefab that has it and set it to the variable in the script you need
prefabThatNeedsTheAnimator.GetComponent<TheScriptWhereYouNeedTheAnimator>().animatorRequired = prefabWithTheAnimator.GetComponent<Animator>();
So I'm working on a save system for my app, and I'm trying to store objects in a GameObject array like so:
public GameObject[ ] entriesInScene;
When I store GameObject in the array it stores the GameObject ID. When I try and instantiate the object later on in the code using this if loop:
foreach (GameObject go in saveObject.entriesInScene)
{
Debug.Log(go);
GameObject entry = Instantiate(go, position, Quaternion.identity);
entry.transform.SetParent(null);
entry.transform.SetParent(scroll.transform);
entry.transform.localScale = new Vector3(1,1,1);
}
It give es me an error of MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object.
Does Anyone know how to fix this or know how to get the GameObject from the ID to make the instantiate work?
Through Unity you won't be able to save entire GameObjects directly through serialization as far as I know. My approach to a similar problem with implementing a save system was to have each object type stored as a prefab, and then I'd save the important values itself in my script (an example being a microwave prefab that a user could place, but I'd store the Vector3 for the position). In most cases you should be able to just store the values that change between instances of a prefab.
I have two gameObjects really close to each others (let's call them A and B), an other one is coming with a certain speed (let it be C). And what I want is: that the object C delete itself and at the same time it delete the object A which it is colliding with.
I am using the onTriggerEnter function with the Delete() method to do it but unfortunatly this delete both gameObjects at the end of the frame. And within this very short time (collision -> delete) the object C which is moving can collide with the object B
So do anyone have a solution to delete the object C which is moving before it collides with the object B?
You have a number of options available to you.
The first, and most drastic, is to use DestroyImmediate. The documents here describe why it might be used, but also warn against its use in general, unless you have a specific reason.
Another option would be to change the Layer of the object, so that the collision of C won't happen during the next FixedUpdate. That should be applied straight away, and stop your objects from colliding. To accomplish this, you'll have to make sure you have a new Layer, and in your physics ( or physics2D ) settings, you'll need to make sure that the layer Object C is on doesn't collide with the new Layer. You can find more about the collision matrix here at the Unity Docs.
A quick code example might look something like this:
public LayerMask noCollisionLayer;
public GameObject ObjectB;
private void OnCollisionEnter ( Collision other )
{
ObjectB.layer = noCollisionLayer;
}
The Unity Manual says the Resources.Load returns the requested asset as an Object.I wonder why could't I use the returned Objectdirectly.For example,I have a Text prefab and I want to add it's instance to the Hierarchy,but the Code below won't work
Text prefab;
private void Start()
{
prefab = Resources.Load<Text>("Prefabs/Text");
GameObject canvas = GameObject.Find("Canvas");
prefab.transform.SetParent(canvas.transform);
}
I must Instantiate the return of the Resources.Load first like below
Text prefab;
private void Start()
{
prefab = Resources.Load<Text>("Prefabs/Text");
GameObject canvas = GameObject.Find("Canvas");
Text text = Instantiate(prefab);
text.transform.SetParent(canvas.transform);
}
I don't know what's the difference between the Instantiate result and Resources.Load result,and what the Instantiate do ,so that it's return can be added to Hierarchy.
Forgive my poor English!
To use the Method Instantiate(GameObject) you would write a new component, create a new variable of type GameObject, attach the component to an GameObject, and fill the variable in the inspector.
To use the Method Instantiate(Resource.Load("object path")) you just need the name/path of the Prefab.
this is extremely useful if you have a huge amount of generated parts in your game (so there are no gameobjects placed in the editor), if you'd want to avoid Resource.Load you'd need some "data-holder-gameobject" placed in an nearly empty scene. edited to make my point a bit clearer
it is aswell helpfull if you have large number of different Prefabs and your method knows the name of the object it wants to build, or you just simply dont want to drag and drop all those prefabs into the inspector window
Resource.Load, loads data from your drive. it's possible that your game is played from a Hard drive, which would mean to load the prefabs the hard drive needs to rotate, position the read-head, and so on.
Instantiate is slow itself even without the need of Resource.Load Instantiate is not that fast. if it happens that you need it very often ( multiple times per second) you should consider some kind of object-pool 1
I have a prefab, which has a script component as MonoBehaviour. This script has 3 public fields as text; which are assigned in the inspector, before saving the gameobject and remove it from the scene.
Now, this works fine if I have a UI element, like a panel. Every text field on the panel, defined in the prefab, is still assigned when the prefab is instantiated at runtime.
This sadly does not work on another prefab that I have made; which is not a UI element. In my case it is a meshgameobject with various components on it (navmesh agent, capsule collider, rigidbody, animator and so on)
I believe this is due the fact that with the UI panel, the elements are already in the gameobject hierarchy, while when the reference is on a different gameobject; Unity does not keep track of them.
This means that I have to always add at runtime via code, the elements that I want to reference on each prefab, if they are not part of the game object itself? In this case I would just avoid to have my references public then, since I won't be using the inspector in this case (every gameobject of this type is instantiated at runtime).
Just checking if there is any other solution to work around this.
Use List to save reference for each generated object.
Lets assume that the object you want to add to store the reference is called meshgameobject.
Example:
List<meshgameobject> meshGOB;
initiaize inside Start function
void Start(){
meshGOB = new List <meshgameobject>();
}
Then create and use list.add() to add reference during runtime like
meshGOB.Add((meshgameobject)Instantiate(prefab, Pos, Quaternion.Identity);
OR
meshgameobject tempGOB= (meshgameobject)Instantiate(prefab, Pos, Quaternion.Identity);
//Do something with meshgameobject
tempGOB.someAction......
then add the reference to the List
meshGOB.Add(tempGOB);
Do not make a perfab which references to other gameobjects in the scene but are not in the hierarchy of the perfabI itself. AFAIK, Unity can not track this kind of references.
Even if Unity supported this kind of prefab, you could not use this kind of prefab in other scenes because the specific references, so it is not make much sense to make a perfab like that. If you have to make it a pefab just because the scene and the game object are maintained by different person, you may use Find() to populate the references at runtime.