- Home /
Passing an instance of a class to different game objects
I am trying to make a product catalog so we can show products, take orders, etc when on different devices and offline to our store.
At the moment I am having trouble passing a instantiated class to another gameobject. I checked some of the similar questions but they did not help me (or I couldn't get them to work with my situation) The way I have it set up is all through UI elements.
First I have the Product Class that holds all the information for a product:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class Product : MonoBehaviour {
public string productName;
public Image productImage;
public string productSKU;
public float productPrice;
public List<string> categories;
}
Then I have a product master where I create all the products:
public class ProductMaster : MonoBehaviour {
public static ProductMaster instance;
public List<Product> product; //List to hold all product data
// Use this for initialization
void Awake(){instance = this;}
void Start () {
AddProducts ();
}
void AddProducts()
{
Product Item1 = new Product ();
Item1.productName = "A Ball";
Item1.productSKU = "BALL";
Item1.productPrice = 39.99f;
Item1.productDescription = "Details1,\n followed by details 2";
Item1.productImage = (Image)AssetDatabase.LoadAssetAtPath("Assets/Images/item-1.jpg", typeof(Image));
product.Add (Item1);
Product Item2 = new Product ();
Item2.productName = "Another Ball";
Item2.productSKU = "BALL2";
Item2.productPrice = 19.99f;
Item2.productDescription = "Details1,\n followed by details 2";
Item2.productImage = (Image)AssetDatabase.LoadAssetAtPath("Assets/Images/item-2.jpg", typeof(Image));
product.Add (Item2);
}
}
And so on for all the products. This all works fine and gets the data into the list.
The next step is that I need to instantiate all the products of a certain category into thumbnails on a canvas. I do this with the following:
public class CategoryProducts : MonoBehaviour {
ProductMaster PM;
public GameObject productThumbnail;
public Canvas viewPort;
// Use this for initialization
void Start () {
PM = ProductMaster.instance;
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown ("c"))
FillCategory ("Balls");
}
void FillCategory(string category)
{
foreach (Product p in PM.product) {
GameObject go = Instantiate (productThumbnail) as GameObject; //productThumbnail has a Product Script on it
go.name = p.productName;
go.transform.SetParent (viewPort.transform, false);
go.GetComponent<Product>() = p; //THIS IS THE PART THAT DOES NOT WORK. HOW CAN I ASSIGN THE DATA FROM p INTO THE PRODUCT ON THE productThumbnail?
Debug.Log (p.productSKU + " " + p.productName);
}
}
}
The instantiated gameobject from the above code has a product class attached to it that I want to assign the data from the PM.product List but it spits out the error:
The left-hand side of an assignment must be a variable, a property or an indexer
The instantiated object is also a button that when the user presses it, it passes the product data again into a canvas that displays all the information such as productName, productPrice, etc.
How do you pass an instance of a class full of data to another gameobject? Or is there another way I should be tackling this issue? I think the best way is for all the parts of the program (there will be 3 canvasses where the same product info need to go to) to reference the one master product list rather than recreating the product in each instance.
Cheers
Answer by JBehreandt · Apr 29, 2016 at 06:28 AM
Why are there two assignments of a product's information -- one on a GameObject instantiated by CategoryProducts and one in a Product script created by ProductMaster? (Maybe they happen at different times, or the internal model needs to be separate from the external representation?) If they need to be separate, and hence copied over, I'd recommend using AddComponent rather than GetComponent after referencing this answer, which discusses reflection. If the product entry and the game object can be created at the same time, see below. I'm guessing that multiple canvas objects would be required -- one with a text component for the product description, one for the product image, etc. -- so no one canvas game object would require every piece of product info.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class ProductMaster : MonoBehaviour {
public List<Product> products;
void Update() {
if(Input.GetKeyDown(KeyCode.C)) {
addProduct ();
}
}
public void addProduct() {
// Create a game object with the name product. Give it two components: Product and Image
GameObject productObject = new GameObject ("Product", typeof(Product), typeof(Image));
// Get a reference in this script to the component on the game object.
Product productScript = productObject.GetComponent<Product> ();
// Get a reference to the UI component image.
Image imageComponent = productObject.GetComponent<Image> ();
// Set the variables in the script component.
productObject.name = productScript.name = "A Ball";
productScript.sku = "BALL";
productScript.price = 39.99f;
productScript.description = "Details1,\n followed by details 2";
productScript.categories.Add ("category1");
imageComponent.sprite = productScript.sprite = Resources.Load<Sprite> ("item-1");
// Add a reference to the script, not the game object to the list.
products.Add(productScript);
}
}
The specific error that is stopping you is that GetComponent() is a function that returns a generic Type, which is assigned to a variable from right to left. Once that's cleared up, there'll be a few more issues that pop up. It's helpful to keep in mind that classes that inherit from MonoBehaviour -- and can be attached to GameObjects as Script Components -- are not instantiated via constructors. Take care not to mix UnityEditor library classes such as AssetDatabase with scripts that attach to objects. If you do, use preprocessor directives like #if UNITY_EDITOR // code #endif and realize that the code between will not be included in a build of the game. Also, do not confuse the Image component which attaches to UI GameObjects with a Sprite, Texture, etc. assets.
Answer by 8r3nd4n · May 02, 2016 at 04:02 PM
Sorry for a late reply, was out of town. Thanks for clearing some of that up in regards to the mono classes. I assumed it worked the same way no matter in that they could also be instantated via constructors.
You are correct in that I was hoping to have only one instance of the product information stored somewhere and that all the canvasses (there would be 3 separate places where it would need to be used, and each displaying only certain info about the product) would just be able to reference this one list of products. All up there are going to be over 200 products and a lot more fields that they contain (a video, some extra pictures) so I was hoping to have the AddProduct script as clean as possible (looked into using a csv file for holding the data but found it not ideal). I have done a test seeing how heavy a load on the system it would be to create 300 products and no sweat:
void Start () {
AddProducts ();
}
public void AddProduct(string pName, string pSKU, float pPrice, List<string> pCategories, string pDescription,string pImagePath) {
// Create a game object with the name product. Give it two components: Product and Image
GameObject productObject = new GameObject ("Product", typeof(Product));
// Get a reference in this script to the component on the game object.
Product productScript = productObject.GetComponent<Product> ();
// Set the variables in the script component.
productObject.name = pName;
productScript.productSKU = pSKU;
productScript.productPrice = pPrice;
productScript.productDescription = pDescription;
productScript.categories.Add (pCategories);
productScript.productImage = Resources.Load<Sprite> (pImagePath);
// Add a reference to the script, not the game object to the list.
product.Add(productScript);
Debug.Log (product.Count);
}
public void AddProducts() {
for (int i = 0; i < 300; i++) {
AddProduct ("Ball" + i.ToString (), "hkhs", 39.99f, "Details1,\n followed by details 2",
"category1", "ball-1");
}
}
So now that everything is in this master list, I should be able to keep referencing the one product master.
Cheers