Unity. After downloading my rawimage is still blank - c#

Hi My scene name is a game.In that scene I am having A main panel that's name is ITEMCONTAINER. In item container I am having a panel whoes name is ITEM. I attached a script in ITEM PANEL. IN that script i am having a game object public,a raw image ,text and how many times loop will continue are public.
In the place of game object i attached my prefab,that contain 1 text and 2 rawimage.
in place of text i attached text component of prefab and same like raw image.
When I run the game the text value I am getting correctly but rawimage is showing blank in runtime.Here i am running my loop 3 times and all three times it create clone of my prefab panel as a child in itempanel
I want rawimage dynamic at my run time
output
prefab
image= in this image , it contains output.here rawimage is blank but text valuecoming perfectly
image = it is my prefab that prefab will be clone during runtime, here it shows image but during runtime , in clone it shows blank
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DynamicData : MonoBehaviour {
public GameObject prefab;
public Text name;
public int numberToCreate;
public RawImage profile;
void Start () {
for (int i = 0; i < numberToCreate; i++)
{
name.text = "a"+i;
StartCoroutine( ImageDownload( profile));
Instantiate <GameObject>(prefab, transform);
}
}
IEnumerator ImageDownload ( RawImage img) {
WWW www = new WWW("https://www.w3schools.com/w3images/fjords.jpg");
yield return www;
Texture2D texure = new Texture2D (1, 1);
texure.LoadImage (www.bytes);
texure.Apply ();
img.texture = texure;
}
}

You are assigning the downloaded image to the profile variable which is not a variable from the instantiated Object. In the loop, you need to get the child of each instantiated Object with transform.Find("profile") then get the RawImage component attached to it with GetComponent and pass it to the ImageDownload function.
Replace your for loop with this:
for (int i = 0; i < numberToCreate; i++)
{
name.text = "a" + i;
GameObject instance = Instantiate<GameObject>(prefab, transform);
//Get RawImage of the current instance
RawImage rImage = instance.transform.Find("profile").GetComponent<RawImage>();
StartCoroutine(ImageDownload(rImage));
}
Please rename public Text name; to something else like public Text userName; because the name is already declared in MonoBehavior you derived your script from.

Related

Script that when an prefab is in an folder called mods, a button appears in the scene and when clicked it spawns the prefab

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);
}
}

Save Object mesh in Assets/Convert Default Asset File to Mesh Asset

I am working on a project where I have a script that combines all the meshes of a gameobjects childs into one mesh while in edit mode. Now the problem is that even though I have managed to then save the mesh into my assets folder it is only saved as a default asset(blank white icon) and not as a mesh that I can then use for other things. Now I would like to know how to get it saved as a mesh asset. I think I could either somehow convert the default asset file to a mesh asset if that is possible, or I could directly save an objects mesh into the asset folder but I dont know if that's possible.
I would be very grateful if you could share code that I could use to do this(it doesnt have to be fance, it should just work).
Here is the code that I have currently:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
[ExecuteInEditMode]
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
// Copy meshes from children into the parent's Mesh.
// CombineInstance stores the list of meshes. These are combined
// and assigned to the attached Mesh.
public class CombineMeshes : EditorWindow
{
[Header("References")]
public GameObject generateFromObject;
[MenuItem("Window/My/MeshGenerator")]
static void Init()
{
CombineMeshes window = (CombineMeshes)GetWindow(typeof(CombineMeshes));
}
private void OnGUI()
{
generateFromObject = (GameObject)EditorGUILayout.ObjectField(generateFromObject, typeof(GameObject), true);
if (GUILayout.Button("Generate"))
{
Generate();
}
}
void Generate()
{
MeshFilter[] meshFilters = generateFromObject.GetComponentsInChildren<MeshFilter>();
CombineInstance[] combine = new CombineInstance[meshFilters.Length];
int i = 0;
while (i < meshFilters.Length)
{
combine[i].mesh = meshFilters[i].sharedMesh;
combine[i].transform = meshFilters[i].transform.localToWorldMatrix;
i++;
}
generateFromObject.transform.GetComponent<MeshFilter>().mesh = new Mesh();
generateFromObject.transform.GetComponent<MeshFilter>().mesh.CombineMeshes(combine);
generateFromObject.transform.gameObject.SetActive(true);
Mesh mesh = generateFromObject.transform.GetComponent<MeshFilter>().mesh;
AssetDatabase.CreateAsset(mesh, "Assets/myAsset");
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(mesh));
AssetDatabase.SaveAssets();
}
}

How to programmatically switch tile palettes in Unity2D

Scenario: User has different tile palettes for each season (Summer, Fall, etc.) and switching between the two using popular Unity techniques would be tedious if the number of tiles in the tileset is greater than 5 or 10. How would said user switch between their tile palettes programmatically, instead of using a wasteful solution like prefab tiles?
This problem seems significant enough that Unity docs would cover it. However I found myself digging through years-old forum posts to come up with my solution. Here's what I came up with, and it's not too complicated.
Create your tilesets. Import your tilesets as multi-sprite spritesheets, and split them using the Unity sprite editor. Do not bother naming each sprite. Each tileset should be organized the same exact way (bushes/trees/objects should be in the same spot on every season's tilesheet). When you are finished, create a folder "Resources" in your "Assets" folder. Inside of resources, create a folder "Spritesheets", and place your spricesheets in it.
Run this renaming script:
using UnityEngine;
using UnityEditor;
using System.Collections;
public class SpriteRenamer : MonoBehaviour
{
public Texture2D[] texture2Ds;
public string newName;
private string path;
private TextureImporter textureImporter;
void Start ()
{
foreach(Texture2D texture2D in texture2Ds){
path = AssetDatabase.GetAssetPath (texture2D);
textureImporter = AssetImporter.GetAtPath (path) as TextureImporter;
SpriteMetaData[] sliceMetaData = textureImporter.spritesheet;
int index = 0;
foreach (SpriteMetaData individualSliceData in sliceMetaData)
{
sliceMetaData[index].name = string.Format (newName + "_{0}", index);
print (sliceMetaData[index].name);
index++;
}
textureImporter.spritesheet = sliceMetaData;
EditorUtility.SetDirty (textureImporter);
textureImporter.SaveAndReimport ();
AssetDatabase.ImportAsset (path, ImportAssetOptions.ForceUpdate);
}
}
}
Attach it to an empty GameObject in an empty Scene (just for simplicity). Drag and drop your spritesheets into the Texture2D array. Set the newName field to whatever you want, it will be the prefix for the name of each sprite in each spritesheet. Finally, run the scene and each spritesheet's sprites will be renamed to make each corresponding sprite have the same name.
We now have each of our seasons' tilesheets modified so each tile is identically named. The next step is to create a Grid object with a child TilePalette. Draw all of your scenery, collision, etc. You can use as many TilePalettes as needed, as long as they are children of the Grid object. Now, create a script called ReskinnableTileBase:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class ReskinnableTileBase : TileBase
{
public Sprite sprite;
public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData)
{
tileData.sprite = sprite;
}
}
Attach this Reskinner script to your Grid object:
using System;
using System.Linq;
using UnityEngine;
using UnityEngine.Tilemaps;
public class Reskinner : MonoBehaviour
{
Sprite[] subSprites;
Tilemap[] tilemaps;
void Start(){
tilemaps = GetComponentsInChildren<Tilemap>();
SetSkin("#INSERT DEFAULT TILE PALETTE NAME HERE#");
}
public void SetSkin(string name){
reloadSprites(name);
foreach(Tilemap tilemap in tilemaps){
for(int x = (int)tilemap.localBounds.min.x; x < tilemap.localBounds.max.x; x++){
for(int y = (int)tilemap.localBounds.min.y; y < tilemap.localBounds.max.y; y++){
TileBase tb = tilemap.GetTile(new Vector3Int(x, y, 0));
Debug.Log(tb);
ReskinnableTileBase rtb = (ReskinnableTileBase)ScriptableObject.CreateInstance(typeof(ReskinnableTileBase));
if(tb == null || rtb == null || tb.name.Length < 1){
continue;
}
Sprite replace = getSubSpriteByName(tb.name);
rtb.sprite = replace;
rtb.name = tb.name;
tilemap.SwapTile(tb, (TileBase)rtb);
}
}
}
}
void reloadSprites(string name){
subSprites = Resources.LoadAll<Sprite>("Spritesheets/" + name);
}
Sprite getSubSpriteByName(string name){
foreach(Sprite s in subSprites){
if(s.name == name){
return s;
}
}
return null;
}
}
And there you go! Now, any time you need to change the skin/season/tilesheet, just use a reference to the Grid's Reskinner script, and call the SetSkin method, like so:
Reskinner reskinner = gridObject.GetComponent<Reskinner>();
reskinner.SetSkin("summer");

Change Unity3D prefab image during runtime

I have an inventory of objects in a game, with image and description.
To represent it, I want a scrollable list with a grid (made with a UI canvas with a scroll view inside), and every element of the grid is a prefab, composed by a UI Panel with an Image and a Text.
I've tried assigning the values of the Image and the Text programmatically in the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PopulateGrid : MonoBehaviour
{
public GameObject prefab;
public Sprite mySprite;
private void Start()
{
Populate();
}
public void Populate()
{
GameObject newObj;
for (int i = 0; i < 20; i++)
{
newObj = (GameObject)Instantiate(prefab, transform); //prefab has image + text
newObj.GetComponentInChildren<Text>().text = "test" + i;
newObj.GetComponentInChildren<Image>().sprite = mySprite; //I've also tried .overrideSprite
}
}
}
The funny thing is, the Text gets correctly updated, while the Image doesn't. I'm accessing them in the same way, but one acts like I want it to and the other one does his thing.
This is the end result:
UPDATE: more details! Here's the code at runtime showing that the Image sprite does indeed get assigned
and here's my inspector:
Since you say that the Panel object itself also has an Image component you do not want to use GetComponentInChildren since it also returns any Image attached to the newObj itself!
Your code doesn't throw an exception but assigns the mySprite to the Image component of the Panel object, not its children called Image.
You would either have to use e.g.
newObj.transform.GetChild(0).GetComponent<Image>()
or as mentioned create your own class and attach it to the prefab like e.g.
public class TileController : Monobehaviour
{
// Reference these via the Inspector in the prefab
[SerializeField] private Text _text;
[SerializeField] private Image _image;
public void Initialize(Sprite sprite, String text)
{
_image.sprite = sprite;
_text.text = text;
}
}
and then do
// using the correct type here makes sure you can only reference a GameObject
// that actually HAS the required component attached
[SerializeField] private TileController _prefab;
public void Populate()
{
TileController newObj;
for (int i = 0; i < 20; i++)
{
// no cast needed since Instantiate returns the type of the prefab anyway
newObj = Instantiate(_prefab, transform);
newObj.Initialize(mySprite, "test" + i);
}
}
Are you sure GetComponentInChildren is pointing to the right Image component? I would create a custom MonoBehaviour class for your prefab, and create a SetImage() method that points to the correct Image. When using GetComponentInChildren, it will return the first component found, and this can lead to unexpected behaviour.
You can do a Debug on newObj.GetComponentInChildren<Image>() to verify that it's the right component. Your code seems to be OK.

Code not allowing letting me disable a script from another script

I'm having an issue where I can't disable a script from the other script - they are both public and within the same package (I think).
Here is my code for the script I'm trying to disable from:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
#if UNITY_EDITOR
using UnityEditor;
#endif
using RTS;
public class PauseMenu : MonoBehaviour {
Canvas canvas;
private Player player;
public Button Button2;
void Start()
{
Debug.Log ("asdf");
player = transform.root.GetComponent< Player >();
canvas = GetComponent<Canvas>();
canvas.enabled = false;
ResourceManager.MenuOpen = false;
Button2.GetComponent<Button>().onClick.AddListener(() => { Resume();});
if(player) player.GetComponent< UserInput >().enabled = false;
}
And the code for the other script:
//sets up what resources we are using
using UnityEngine;
using System.Collections;
using RTS;
public class UserInput : MonoBehaviour {
//sets up a private variable for only this class - our player
private Player player;
// Use this for initialization
void Start () {
//this goes to the root of the player ie the object player and allows us to
player = transform.root.GetComponent< Player > ();
}//end Start()
So the part that is not working is:
if(player) player.GetComponent< UserInput >().enabled = false;
And the code runs and then causes the runtime error:
NullReferenceException: Object reference not set to an instance of an object
PauseMenu.Pause () (at Assets/Menu/PauseMenu.cs:40)
PauseMenu.Update () (at Assets/Menu/PauseMenu.cs:29)
Here is a picture showing my scene hierarchy and components:
The issue here is that you try to execute transform.root.GetComponent< Player >(); from within PauseMenu, which is on the "Canvas" object.
The problem with that is that the topmost transform in the hierarchy of your "Canvas" object (which is what transform.root returns) is, well, the transform of the "Canvas" object - which is in no way related to the UserInput script you are trying to access. For this script to actually work, you would need the transform of your "Player" object, which is the object that actually has the UserInput script.
My suggestion is to eliminate the need to run GetComponent() at all - create a public UserInput variable in your PauseMenu class, then (while selecting your "Canvas") in the editor, drag the "Player" object into that new field. This will cause the UserInput script of your "Player" object to be accessible within the PauseMenu.
So your PauseMenu script might look like:
public class PauseMenu : MonoBehaviour {
Canvas canvas;
public UserInput playerInput; // Drag the Player object into this field in the editor
public Button Button2;
void Start()
{
Debug.Log ("asdf");
canvas = GetComponent<Canvas>();
canvas.enabled = false;
ResourceManager.MenuOpen = false;
Button2.GetComponent<Button>().onClick.AddListener(() => { Resume();});
playerInput.enabled = false;
}
}
Hope this helps! Let me know if you have any questions.
(An alternative is to use GameObject.Find("Player") to get GameObject of "Player". This needs a bit more code but doesn't use the editor.)
I would say your player = transform.root.GetComponent< Player >(); arrives null.
So you are trying to disable something that doesnt exist.
Enter debug mode and see if your player is null or not.

Categories

Resources