Search Unity

Instantiation of a custom class

Discussion in 'Scripting' started by sidsidsid16, Feb 21, 2020.

  1. sidsidsid16

    sidsidsid16

    Joined:
    Feb 21, 2020
    Posts:
    5
    I have a class named Star:

    Code (CSharp):
    1. class Star
    2. {
    3.     public int primaryID;
    4.     public string properName;
    5.     public string HIPID;
    6.     public string HDID;
    7.     public string HRID;
    8.     public string GLID;
    9.     public string BFID;
    10.     public decimal rightAscension;
    11.     public decimal declination;
    12.     public string magnitude;
    13.     public string colourIndex;
    14.     public int scale;
    15.     public int red;
    16.     public int green;
    17.     public int blue;
    18.     public bool isSimulated;
    19.     public double x;
    20.     public double y;
    21.     public double z;
    22.  
    23.     public void setDetails(int primaryID, string properName, string HIPID, string HDID, string HRID, string GLID, string BFID, decimal rightAscension, decimal declination, string magnitude, string colourIndex)
    24.     {
    25.         this.primaryID = primaryID;
    26.         this.properName = properName;
    27.         this.HIPID = HIPID;
    28.         this.HDID = HDID;
    29.         this.HRID = HRID;
    30.         this.GLID = GLID;
    31.         this.BFID = BFID;
    32.         this.rightAscension = rightAscension;
    33.         this.declination = declination;
    34.         this.magnitude = magnitude;
    35.         this.colourIndex = colourIndex;
    36.         decimal deg2rad = 0.01745329251994329576923690768489m;
    37.  
    38.         this.isSimulated = true;
    39.  
    40.         // Decimal datatype is used to make sure that values are very accurate and precise
    41.         decimal degrees_ra;
    42.         decimal degrees_dec;
    43.         decimal radians_ra;
    44.         decimal radians_dec;
    45.  
    46.         degrees_ra = Decimal.Multiply(rightAscension, 15);
    47.         degrees_dec = declination;
    48.  
    49.         radians_ra = Decimal.Multiply(degrees_ra, deg2rad);
    50.         radians_dec = Decimal.Multiply(degrees_dec, deg2rad);
    51.  
    52.         // Converted from decimal to double because the Math library cannot work with decimals
    53.         float distanceStars = 19113;
    54.  
    55.         this.x = (distanceStars * Math.Cos(decimal.ToDouble(radians_dec)) * Math.Cos(decimal.ToDouble(radians_ra)));
    56.         this.y = (distanceStars * Math.Cos(decimal.ToDouble(radians_dec)) * Math.Sin(decimal.ToDouble(radians_ra)));
    57.         this.z = (distanceStars * Math.Sin(decimal.ToDouble(radians_dec)));
    58.     }
    59.  
    60.     public Vector3 getVector()
    61.     {
    62.         return new Vector3((float)z, (float)y, (float)x);
    63.     }
    64. }


    There are many of these stars and I want to instantiate them at run-time:

    Code (CSharp):
    1. void plotStars()
    2. {
    3.     int i = 0;
    4.     while (i < (StarDataBank.Instance.NumOfStars))
    5.     {
    6.         string name = StarDataBank.Instance.StarName[i];
    7.         string HIP = StarDataBank.Instance.StarIDHIP[i];
    8.         string HD = StarDataBank.Instance.StarIDHD[i];
    9.         string HR = StarDataBank.Instance.StarIDHR[i];
    10.         string GL = StarDataBank.Instance.StarIDGL[i];
    11.         string BF = StarDataBank.Instance.StarIDBF[i];
    12.         decimal RA = Convert.ToDecimal(StarDataBank.Instance.StarRA[i]);
    13.         decimal Dec = Convert.ToDecimal(StarDataBank.Instance.StarDec[i]);
    14.         string Mag = StarDataBank.Instance.StarMag[i];
    15.         string ColI = StarDataBank.Instance.StarCI[i];
    16.  
    17.         var star = new Star();
    18.         star = Instantiate(ObjectStar, transform.position + star.getVector(), Quaternion.identity);
    19.  
    20.         star.transform.parent = StarObject.transform;
    21.         star.transform.localScale = new Vector3(star.scale, star.scale, star.scale);
    22.         i++;
    23.     }
    24. }
    But I am experiencing a lot of errors.

    1. Unity isn't instantiating the Stars because it can't convert UnityEngine.Transform to Star
    2. Star doesn’t contain definition for transform
    Is there a way to assign a class as a gameobject so I can instantiate it?
     
  2. olivecrow

    olivecrow

    Joined:
    Jul 15, 2017
    Posts:
    24
    I think you need to inherit Monobehaviour to Star.
    only Monobehaviour can be a game object and it can't instantiated by "new" keyword.

    Code (CSharp):
    1. public class Star : Monobehaviour
    2. {
    3.     // in this case, you need to write datas in here.
    4. }

    Or if you want just to make a gameobject contain a "Star" as a data,

    Code (CSharp):
    1. public class StarGameObjet : Monobehaviour
    2. {
    3.     public Star;
    4. }
    Code (CSharp):
    1. var star = new Star();
    2. var starGameObject = Instantiate(prefab);
    3.  
    4. starGameObject.star = star;
     
  3. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,113
    You can also add the script to gameobject with AddComponent<Star>() but it has to inherit from MonoBehaviour

    [edit]
    btw, what you really want is a MonoBehaviour script that you attach to a gameobject, make a prefab out of it, and then instantiate these prefabs through another MonoBehaviour script that serves as a factory/instantiator.
     
  4. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    You have two problems: You are trying to use the GameObject.Instantiate() method to create instances but Instantiate only works for classes that inherit from the Unity Object class (including GameObjects).

    Secondly, you are attempting to set values for your star transform, but your star class does not have any reference to a Transform component, or any member called "transform" at all. A monobehaviour has a member called transform so when you write a script that inherits from monobehavior, then you can use transform.

    As others have mentioned, you probably meant to inherit from monobehavior. If your script inherits from monobehavior, then you have access to monobehaviors members (including transform) as well as your own. Remember, though, that you will need to create a GameObject for each of your stars in that case.

    Edit: By the way, have you done any C# coding outside of Unity before?

    Edit 2: If you change Star so that it does inherit MonoBehaviour then you can create and instance like this:
    Code (csharp):
    1.  
    2. var star = Instantiate(ObjectStar, transform.position + star.getVector(), Quaternion.identity);
    3. star.AddComponent<Star>();
    4.  
    That should work, but I don't know what ObjectStar is. If it's a prefab, than you can just attach your Star component to the prefab and you don't need to use AddComponent.

    Edit 3: On other thing- I thought I should mention that since Star itself does not reference MonoBehaviour members, Star doesn't necessarilly need to inherit MonoBeviour, it could also be included as a member of a class that inherits MonoBehaviour. You just need some MonoBehavior somewhere if you want to attach an object to a GameObject.
     
    Last edited: Feb 21, 2020
  5. sidsidsid16

    sidsidsid16

    Joined:
    Feb 21, 2020
    Posts:
    5
    Where it says
    Code (CSharp):
    1. var star = Instantiate(ObjectStar, transform.position + star.getVector(), Quaternion.identity);
    , the
    Code (CSharp):
    1. star.getVector()
    method call doesn't work because star is being called before it is declared.
     
  6. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    Just delete the star.getVector(). Your x,y, and z are not intialized, so it's not going to have any valid value.
     
  7. sidsidsid16

    sidsidsid16

    Joined:
    Feb 21, 2020
    Posts:
    5
    I've set the Star class as MonoBehaviour. Also, in my class some of the public variables aren't showing the inspector. For example, in a file called Simulation.cs:
    Code (CSharp):
    1. public class test : MonoBehaviour
    2. {
    3.     public int Test;
    4. }
    5.  
    6. public class Simulation : MonoBehaviour
    7. {
    8.     public int anotherTest;
    9. }
    The variable anotherTest shows in the Unity Inspector, but Test doesn't show up. Is there a way to fix this?

    EDIT: I've tried using [SerializeField] above public int Test; but that doesn't fix it
     
  8. kdgalla

    kdgalla

    Joined:
    Mar 15, 2013
    Posts:
    4,639
    In Unity, each MonoBehaviour has to be in it's own separate file and the file needs to have the same name as the class. This is just a quirk of how the editor works.
     
  9. sidsidsid16

    sidsidsid16

    Joined:
    Feb 21, 2020
    Posts:
    5
    I've moved the Stars class to another script, all my public variables are now showing. I have another issue, this line:
    Code (CSharp):
    1. var star = Instantiate(prefabStar, transform.position + getVector(), Quaternion.identity);
    Returns a NullReferenceException. prefabStar has been attached to the prefab and the getVector method works properly.

    What might be the issue here?
     
  10. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,113
    obviously either your prefabStar is null or getVector() returns null, but I'm guessing it would be a different error.
    can't you just stress test these things with Debug.Log?

    I mean if you suspect something's null, why can't you just
    if(prefabStar == null) Debug.Log("yes it is prefabStar that's pointing to null");
     
  11. sidsidsid16

    sidsidsid16

    Joined:
    Feb 21, 2020
    Posts:
    5
    Despite setting the prefabStar to the prefab in the editor, when the class is instantiated, it for some reason returns the prefabStar as empty. I probably need to try to attach it during runtime. Any idea on why it's doing that?
     
  12. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,113
    you need to make a serialized public var in your MonoBehaviour and assign your prefab to that var from an inspector.
    there are other ways to make this work, but this is the simplest ever, and works perfectly for what you're trying to achieve.

    Code (csharp):
    1. public class MyScript : MonoBehaviour { // manually add this script to an empty gameobject in the scene
    2.  
    3.   public GameObject prefab; // this will show up in your inspector, drag prefab onto it
    4.  
    5.   public void Start() {
    6.     // Instantiate prefab here, by referring to the above var; you'll need to hit play for this to work
    7.   }  
    8.  
    9. }