I am trying to add same components to different game objects in a scene in Unity. To make it faster I am trying to write a script that will do this for a list of game objects like (enemy1, enemy2, enemy3...).
I know that adding a script named Enemy I will do:
gameObject.AddComponent<Enemy>();
But the problem is once I stop the play mode the component is gone. Is there a way to achieve this?
You can directly select all the game objects (the list of enemies you mentioned) from the Hierarchy by holding ctrl and then add in the inspector the script Enemy to all of them.
However, if you want to use a script to do it, which can be executed outisde of the Play Mode you need to add ExecuteInEditMode before the script, like this:
[ExecuteInEditMode]
public class TriggerEdit : MonoBehaviour
{
// List of GameObjects
String[] enemyList = {"enemy1", "enemy2", "enemy3"};
void OnEnable()
{
foreach(String enemy in enemyList){
go = GameObject.Find(enemy);
go.AddComponent<Enemy>();
}
}
}
Then you need to add that script to any game object in your scene. Everytime you want to trigger the script you just need to disable and enable the script TriggerEdit in the editor:
One problem with this approach is that everytime you enable the script, it will add a new component, independently if there is already a compoment of type Enemy in the game object, so you may end up with a lot of Enemy components. Something you can try then is to clean all Enemy components in the scene before adding anything else new. For example:
object[] enemiesToDelete = GameObject.FindObjectsOfType<Enemy>();
foreach(UnityEngine.Object enemyComponent in enemiesToDelete)
{
DestroyImmediate(enemyComponent);
}
Related
I am currently trying to build a shop for my game. The shop is a list, that will be displayed onscreen and consists of Prefabs that each have a button component. On click, a hidden panel should be visible and different UI elements should be adjusted. I know that you can't directly reference GameObjects from a prefab, and I tried workarounds like a reference script from the actual scene and I am worried that using FindObjectsOfTypeAll() will be too slow, especially if I want to extend my game later on.
Below you can see my code:
public void LoadStore(PrisonerObject _prisObj)
{
//Here I am trying to get the references from a seperate script
GameObject Panel1 = reference.ReturnShopPrisonerContainer();
Panel1.SetActive(false);
GameObject Panel2 = reference.ReturnPrisonerPreviewContainer();
Panel2.SetActive(true);
}
//This code is in a different Script
public GameObject ReturnShopPrisonerContainer()
{
ShopPrisonerContainer = GameObject.Find("ShopPrisonerContainer");
return ShopPrisonerContainer;
}
public GameObject ReturnPrisonerPreviewContainer()
{
PrisonerPreviewContainer = GameObject.Find("PrisonerPreviewContainer");
return PrisonerPreviewContainer;
}
The LoadStore method will be called when the Button (on the prefab) is pressed.
I read a lot about this problem, but I can't seem to find a suitable solution for my problem here. I found someone saying there is a different approach to this problem, but unfortunately he didn't really explain his alternative approach. Does anyone have any ideas how I can fix this?
As I understand you need to activate game object after clicking on the game object created from prefab. If yes you can just set listener on prefab's button
// monobehavior on scene that creates objects from prefabs
class PrefabCreator : MonoBehaviour
{
...
private void InstantiatePrefab(GameObject prefab)
{
var obj = Instantiate(prefab, ...);
obj.GetComponent<Button>().OnClick.AddListener(OnClick);
}
private void OnClick()
{
// click handling
}
}
I'm learning unity3d and c# right now with c++ and c knowledge. However, I'm confused with this line of code.
private Gameobject cubePrelab;
This is a simple line of code which "defines the object that we want to spawn" according to the lecturer.
Then he immediately do things like:
Instantiate(cubePreLab, ...,...)
which clones the object according to the documentation online.
I'm confused about the first line of code which it seems like we are just defining an object without actually initializing it. However, the result is with these two line of code, we can actually create a box on the screen but I'm confused why it is a box instead of maybe a trangle.
I suggest you read about Unity Prefabs
Since you're new to Unity, I assume you've started off by putting a few objects -- such as a cube -- into your scene right? The Unity Editor makes it easy to put objects into your scene while you're designing your game, but what if you wanted to dynamically add objects into your scene while you're playing your game?
For example, imagine that you created a scene that has a cannon in it, and every time the player hits the Space key, you want to fire a cannonball. When you create your Scene in the Unity editor, you put your cannon in your scene, but how do you add cannonballs while you're playing the game?
You could have a bunch of code that creates a cannonball from scratch every time you fire one, but that's a very time consuming and error-prone way of doing it. This is where prefabs come in. A prefab is like a blueprint for an object that you're going to add to your scene later. So a cannonball prefab would be an object that you design in the Unity Editor just like any other Unity object that you're adding to your scene. You could assign its size, its material, its color, its attack power, and so on through the Unity Editor (no code needed).
First you would create a prefab in the Unity Editor for your cannonball.
After you create a cannonball prefab, you would add a property on your Cannon class such as public GameObject cannonballPrefab, and you'd drag your cannonball prefab from the Unity editor into the "Cannonball Prefab" property of the Cannonball component on your cannon object in the Unity Inspector. So if you only look at the C# code, it looks like the cannonballPrefab field is never getting initialized. However, you are initializing it by dragging a prefab into it in the Unity Editor. To reference your initial question, this is also how Unity knows to create a box and not a triangle in your example. Unity will create an instance of whatever your prefab is.
Then within your Cannon code, you can instantiate an instance of your cannonballPrefab while you're playing the game each time you want to add a cannonball into your scene.
Now when you call Instantiate(cannonballPrefab... Unity adds an instance of your cannonball into your scene. Then you'd probably do some additional initialization by assigning it an initial position, an initial speed, an initial direction, and so on.
Also, like Pac0 said, the tutorial probably has public GameObject cubePrefab (not private) so that you can drag a reference into it from the Unity Editor. Alternatively you could keep it private and add the [SerializeField] attribute to it like below. Unity won't let you assign a private field from the editor unless it has the [SerializeField] attribute on it.
[SerializeField]
private GameObject cubePrefab;
About a month into making my first game, I have realized that I am very confused when it comes to attaching gameobjects as classes to another game object's script. That's a mouthful so here's my issue.
My Game.cs attached to Game (gameobject) has
public Player player;
My Player.cs is attached to a Player (gameobject) prefab
Why can I drag a Player gameobject, that has a player script, into the Game gameobject's "player" field? How does that make sense? It should be
public GameObject player;
Then I would drag my prefab gameobject "Player".
The reason why this confuses me is, If i Instantiate "player", am I instantiating a gameobject? It seems not, because I cannot do this:
GameObject newPlayer = Instantiate(player, new Vector3(1,1,1), Quaternion.identity) as GameObject;
newPlayer.transform.SetParent(GameObject.Find("Level"));
If I do I will get the error the newPlayer is null.
A script is actually a Component object like any other object (most of the time).
It is technically not too easy to drag a Component object from an inspector onto another slot in another inspector. Probably thats why they made this "shorthand", when you can drag the actual GameObject instead from the hierarchy.
If the dragged GameObject has a matching component to a slot, it counts as you have dragged the Component itself.
You cannot instantiate a script Component using Object.Instantiate, you'll always instantiate a GameObject this way, see the docs. If you need the script, simply get the component from the brand new instance.
It can be confusing indeed, I personally prefer naming convention something like:
public GameObject playerObject;
public Player player;
Unity. by default, will cast any gameobject into the possible component, for example, if you have a Transform in your script and pass a gameobject (as a lot of tutorials do), it will automatically cast to the transform of given gameobject.
The main problem with that is simply that if you try to attach an object without Player script, it will probably crash in one way or another if you don't check the value.
Anyway, while you are working with your own scene and are sure the player gameobject has the necessary script, it won't be a problem in any way
Oh, about the last part, attaching components is common for already instantiated objects, to instantiate from a component you should get the parent game object of that script, and it would not make sense as you could easily attach the prefab directly
I don't remember now exactly how, sorry
I would like to create gameObjects (text, 3d stuff, etc.) from scripts and save them in the scene.
For example: If I use a script like this,
public class ExampleClass : MonoBehaviour
{
public void Start()
{
GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
}
}
the "plane" will be add in Hierarchy temporarily (just after you press start).
I'm looking for some way to create a lot of gameObjects automatically (through a script, api, etc.) and save them in the hierarchy.
you are talking of persistent GameObject after stopping scene i suppose.
The only possibility to make gameObject instance pop inside your scene hierarchy and stay after scene played and stopped is to use CustomEditors.
You have to know, unity editor is based on Unity Gui, so you can easily add buttons make it run some specific script coded by you, inside windows menu (for example).
But you can also custom the mouse right click on scene hierarchy to allow peoples to create instances of a allowed gameObject and add this created instance directly on child of previously clicked gameobject from the scene etc...
Or make create your own tools script, and add it as component on Gameobject and with specific layout for it and rendered by Unity Editor.
For use customEditor step by step :
1 - Create a folder named Editor inside Assets/ root project hierarchy
2 - Create a script like bellow, which is using reference to UnityEditor and add you could use the commented Attribute. At the end you have to make your class extend From Editor class.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
// uncomment this line bellow if you want to create customEditor script which you will be able to use on gameObject as component.
// typeof give script type , it's a script created as component and extending from Monobehaviour, he contain value etc.. he could be manipulated from this CustomEditor script via button who call Methodes.
//[CustomEditor(typeof(YourScriptComponent))]
public class MyNewCustomEditor : Editor
{}
for more examples of customEditors script look at unity doc: http://docs.unity3d.com/ScriptReference/Editor.html
3 - Create methodes to be used and called out of scene Playing mode.
you have to create buttons inside OnInspectorGUI() function which will call your methodes for instantiate inside scenes some GameObjects.
4 - WARNING , To instantiate resources like prefabs etc, you have to put yours needed resources inside folder called Resources and use inside your script the Resources.Load() methode.
see the doc for more information , it's pretty simple to use : http://docs.unity3d.com/ScriptReference/Resources.Load.html
Hope it will help, see You.
There was a similar question asked over here.
You want be making an Editor Script then using pretty much the same logic you would use at runtime. Here is the Unity Docs on editor scripts.
You can just make a C# script and put it in the "Editor" folder. If you want it to appear in the editor as a dropdown option you can throw in "[MenuItem("MyTools/CreateGameObjects")]" before a function as shown in the other Stack Overflow answer.
I'm new to Unity3D and looking for some basic information.
I'm used to OO programming, but I cannot quite see how to access the objects from script.
I created an object, made it a prefab (plan on using it many times) and the object has text on it.
The text uses a Text Mesh. I'm using C#.
How do I thru code, simple example on start, instantiate a new prefab object called Tile at 0,0?
How do you access the text Mesh part of the object to change the text?
I sure there is something simple I'm not picking up on.
Just having trouble understanding how to connect the code to the objects and vice versa.
Updated:
Also wanted to note, I'm trying to load multiple objects at the start, if that makes a difference in the answers.
Update2:
Just wanted to explain a little more what info I was missing when tying the mono code to the unity interface.
In Unity:
Created any object and turn it into a prefab.
Created a second empty game object, place it somewhere in the play view area.
Created a script on the Empty game object.
In Mono code editor:
Created 2 public variables (C#)
public GameObject spawnObj;
public GameObject spawnPoint;
void Update () {
Instantiate (this.spawnObj, this.spawnPoint.transform.position, this.spawnPoint.transform.rotation);
}
Back in Unity:
Select the Empty Game Object.
In the script Component, you should see the 2 vars.
Drag your Prefab Object into the var spawnObj.
Drag the Empty game object into the var spawnPoint.
I did this is the Update, not to smart, but it spawned a cube or 2 or more, spawning from code is all I wanted to understand.
AD1: It's GameObject.Instantiate:
var go=GameObject.Instantiate(prefab, Vector3.zero, Quaternion.Identity) as GameObject;
A prefab is an asset-like GameObject that is used as a template for scene GameObjects.
To use a prefab you have to drag a GameObject to the project window and reference it in code in one of two ways:
Using resources, var prefab=Resources.Load("my-prefab") will load the project file Resources/my-prefab. Note the use of the special "Resources" directory - it's a magic name that is required.
Using a reference, in a MonoBehaviour add a public GameObject prefab field. Then on a GameObject using this class you can drag and drop your prefab from the project window to create a reference to it. You can then use the prefab field in your code. No "Resources" directory needed here.
Prefer option 2, as all resources are in the final binary, while normal assets are trimmed when possible.
AD2: get the TextMesh compontent and modify text:
go.GetComponent<TextMesh>().text="new text";