I am trying to create button in C# code using an existing Prefab. All I found on the website was something like
public GameObject a;
public RectTransform ParentPanel;
void Start()
{
for (int i = 0; i < 5; i++)
{
GameObject goButton = (GameObject)Instantiate(a); /error
goButton.transform.SetParent(ParentPanel, false);
goButton.transform.localScale = new Vector3(1, 1, 1);
Button tempButton = goButton.GetComponent<Button>();
}
}
In Unity project I have Prefab called "ButtonPrefab" where I put Button Object. There is an error in below line
UnassignedReferenceException: The variable a of NewBehaviourScript has not been assigned.
You probably need to assign the a variable of the NewBehaviourScript script in the inspector.
I am new to Unity. How is it come that not assigned var a can give me button using Instantiate()? And why do I have this error?
You can instantiate prefabs very easily from within a Resources folder. Make a new folder within your project's Assets folder called Resources. It must be named Resources for this to work properly. Then you can make your button like this:
GameObject button = Instantiate(Resources.Load("myButton", typeof(GameObject))) as GameObject;
Assuming your prefab is named "myButton."
Related
I wanted to make a simple mod support script but it got tedious very fast. The goal is that people can make prefabs and the put them into the game to give that mod idea. To specify my problem I want to make a script that (on the exported Windows version) checks if there is a mods folder in the resources folder if that exists it will check for prefabs in the mods folder if there are it will make a ui button pop up in the scene with the name of the prefab then when you click it, it spawns the prefab at 0,0,0.
For anyone wanting a picture with how that would have looked here is the game it would have been a sort of spawn menu with mods showing up as the buttons like the pictures of the game.
So I made the script below but it just never worked, like it did find the mod folder but it does not want to spawn the prefab with a button, but other times it did not find the mods folder in the resources folder. I don't know what to do any more.
using UnityEngine;
using UnityEngine.UI;
using System.IO;
public class ModLoader : MonoBehaviour
{
public GameObject buttonPrefab;
public VerticalLayoutGroup verticalLayout;
private string modFolder = "Mods";
private string modPath;
private void Start()
{
modPath = Path.Combine(Application.dataPath, "Resources", modFolder);
if(Directory.Exists(modPath)){
// Get all prefabs in the mod folder
Object[] prefabs = Resources.LoadAll(modFolder, typeof(GameObject));
for (int i = 0; i < prefabs.Length; i++)
{
GameObject prefab = (GameObject)prefabs[i];
// Create a button for each prefab
GameObject button = Instantiate(buttonPrefab, verticalLayout.transform);
button.GetComponentInChildren<Text>().text = prefab.name;
int index = i;
button.GetComponent<Button>().onClick.AddListener(() => SpawnPrefab(index));
}
}else{
Debug.Log("Mod folder not found");
}
}
private void SpawnPrefab(int index)
{
// Instantiate the prefab at position (0,0,0)
Object[] prefabs = Resources.LoadAll(modFolder, typeof(GameObject));
GameObject prefab = (GameObject)prefabs[index];
Instantiate(prefab, new Vector3(0, 0, 0), Quaternion.identity);
}
}
I am instantiating a prefab thru a script in Unity. It's kind of working but not really.
The prefab shows up in the hierarchy with the correct name but in the scene, it cannot be seen.
I have looked through every question I saw, that was similar but unfortunately, I couldn't solve my problem. I tried changing the Vector in the script and the position of the prefab itself.
I appreciate any help.
public class ButtonControler : MonoBehaviour
[SerializeField] private Button[] buttonsList;
public GameObject button;
public void Awake()
{
InitializeButtons();
}
private void InitializeButtons()
{
for (int i = 0; i < CsvManagerDownloader.experiments.Count; i++)
{
string buttontext = "Experiment" + i;
GameObject newButton = Instantiate(button, new Vector3(0, 0, 0), Quaternion.identity);
newButton.GetComponentInChildren<Text>().text = buttontext;
}
(This script can only be called after CSVManagerDownloader, since the number of buttons is gathered from that script.)
It seems that you are trying to instantiate an object that is supposed to be used inside Canvas (unity UI system) in the world space.
Canvas component on the root object is needed to render all child UI elements like Button, Text, Image, etc.
So, if you want your instantiated object with the Button component to be visible, make sure, that you place it in the hierarchy with the Canvas component attached to any of its parents.
Also, make sure that the EventSystem component is present at the scene to make Buttons work.
When I try to add a prefab to my instantiated gameobject, I get an error:
Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption
When I call this script for the first time, everything works fine. There are a lot of similar questions and answers. However, I could not solve my problem with them.
Thanks for the help :)
GameObject coralWoodBundle = Resources.Load("Base/coral_wood_bundle") as GameObject;
GameObject woodlBundle = Instantiate(coralWoodBundle) as GameObject;
woodlBundle.transform.SetParent(this.gameObject.transform);
Related script
public class FallingWoodPackScript: MonoBehaviour
{
public List<FallingWoodScript> fallingWoodScripts;
public void Start()
{
RefillWood();
}
public void RefillWood()
{
GameObject coralWoodBundle = Resources.Load("Base/coral_wood_bundle") as GameObject;
GameObject woodlBundle = Instantiate(coralWoodBundle) as GameObject;
woodlBundle.transform.SetParent(this.gameObject.transform);
woodlBundle.transform.localPosition = new Vector3(1f, 2.7f, 0);
woodlBundle.transform.localRotation = Quaternion.Euler(new Vector3(0, 0, -90));
fallingWoodScripts = new List<FallingWoodScript>();
foreach (Transform child in woodlBundle.transform)
{
fallingWoodScripts.Add(child.GetComponent<FallingWoodScript>());
}
}
}
I had this error quite a while ago and in my opinion its phrasing is a bit misleading.
Maybe you understand it better like this:
Setting the parent TO a transform which resides in a prefab is disabled to prevent data corruption
My guess here is that the FallingWoodPackScript reference (=this) you are calling RefillWood or Start via script on is actually a Prefab reference and therefore this.gameObject.transform is as the error says a transform which resides in a prefab.
Make sure you are calling the RefillWood (or Start) only on an actual instance in the scene.
I have a Script in my main Assets folder called BezierWalk.cs
In another script, Spawn, I'm trying to instantiate objects from Prefab Sphere and attach BezierWalk.cs to them.
Spawn script:
public class Spawn : MonoBehaviour
{
public GameObject Sphere;
//string ScriptName = "BezierWalk";
void Start()
{
Vector3 vSpawnPos = transform.position;
for (int i = 0; i < 20; i++)
{
var objectYouCreate = Instantiate(Sphere, vSpawnPos, transform.rotation);
//objectYouCreate.AddComponent<T>("Assets/BezierWalk.cs");
//objectYouCreate.AddComponent(typeof(ScriptName)) as ScriptName;
//objectYouCreate.AddComponent<ScriptName>();
//var myScript = Sphere.AddComponent<BezierWalk.cs>();
vSpawnPos.z += 20;
}
}
You can see commented out attempts...
How I am supposed to do this properly? Thank you.
If you look at how you reference components in unity, the answer should be clear - did you try any of the ones you listed?
Reference: https://docs.unity3d.com/ScriptReference/GameObject.AddComponent.html
The normally used is as it is easy reading
objectYouCreate.AddComponent<ClassName>();
You can use
objectYouCreate.AddComponent(typeof(ClassName));
the .cs is for humans, its your readable version. so you would never need the .cs reference in your code.
note: I mentioned it as ClassName rather than scriptname, as while they are the same in monobehaviors in unity, it isnt the same anywhere else in c# so, the important bit is not the name of the file you made, but the name of the class within it.
Another way is to have prefabs, make a prefab of your object with all the components you need already on it.
If your script lies within certain namespace, you should follow the following format
GameObject.AddComponent(typeof(namespace.className));
I am trying to add items to my Canvas dynamicly in C#.
Here is what I am trying to do
public class MyScript : MonoBehaviour
{
private List<GameObject> _buttons;
private GameObject _canvas;
public MyScript()
{
_buttons = new List<GameObject>();
}
// Use this for initialization
void Start()
{
for (int i = 0; i < 3; i++)
{
var button = Instantiate(Resources.Load("myButton", typeof(GameObject))) as GameObject;
if (button == null) continue;
button.GetComponent<RectTransform>().position = new Vector3(i, i, 0);
}
}
}
I have my buttonPrefab which is inside of Canvas. After debug I see my new buttons created but they are not in Canvas and its normal because I didnt add them there in code. The point is that I dont have any idea how to add new buttons to Canvas.
Also how I can add OnClick event if buttons are GameObjects and I cant cast it to Button?
Can someone help me ?
Answering how to instantiate: when doing so, you need to rember about few things.
But first lets show some code:
for (int i = 0; i < 3; i++)
{
var button = (GameObject)Instantiate(Resources.Load("myButton", typeof(GameObject))) as GameObject;
if (button == null) continue;
button.transform.SetParent (referenceToCanvas.transform);
button.transform.localScale = Vector3.one;
button.transform.localRotation = Quaternion.Euler (Vector3.zero);
button.GetComponent<RectTransform>().anchoredPosition3D = new Vector3(i, i, 0);
}
When instatiating GameObjects Unity3D creates them in world space with given scale and rotation. When you set the canvas as parent sometimes the scale is set to zero or just not what you want. The same applies to rotation. So that is why I add these lines of code everytime I dynamicaly populate UI.
Of course referenceToCanvas is reference to canvas object ;)
1-) In order to make new buttons added in Canvas you need to make your canvas object parent of these buttons, you need to use setParent method take a look at here
http://docs.unity3d.com/ScriptReference/Transform.SetParent.html
2-)For your second question you can easily achieve that just add a collider to your object which you want to click and add a script to the object as well. And add OnMouseDown() method to this script, whenever you click this object this method will be called.
For 1 see Burak, use Transform.SetParent.
For 2 I'd recommend creating an empty GameObject and add a UI Button to it and what ever you need in addition. Make this a prefab and instantiate it.