Search Unity

C# help with manipulating instantiated variables...

Discussion in 'Scripting' started by welby, May 23, 2011.

  1. welby

    welby

    Joined:
    Mar 22, 2011
    Posts:
    549
    Hi guys,.

    I have been lurking around enjoying the Showcase forums, and have been pretty successful finding out what I need on the interwebz,...but I spent all weekend on this problem and cannot figure it out. I am hoping someone here can help!

    First off,..C#.

    I have a RigidBody prefab named 'newCard'. Attached with a C# script named 'cardVars'.
    Within 'cardVars' are two variables, an int count and a string cardName.


    (ya'll see where this is going don't you? :p)

    I have a 'GameObject' in my Hierarchy that holds my main script named, 'generator'.
    Within that script, I make a button that instantiates the preFab"newCard'.(declared 'spawnCard') at a specific location in the world; on a sphere named birthBall.


    QUESTION: How on earth can I access the two variables in 'cardVars.cs' and change their values/string???


    The following example runs,.but gives one error:

    Unity3D berates you exclaiming:


    preFab code 'cardVars' attached to 'newCard':
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class cardVars: MonoBehaviour {
    5.  
    6.     public string cardName;
    7.     public int count;
    8.    
    9.     void Start () {
    10.     }
    11.    
    12.     public void OnMouseEnter()
    13.     {
    14.         Debug.Log(" Name=  " +cardName);
    15.         Debug.Log(" Count=  " +count);
    16.     }
    17.  
    18.     void Update () {
    19.    
    20.     }
    21. }
    generator.cs Code attached to a GameObject in Hierarchy:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class generator : MonoBehaviour {
    5.  
    6.     public Rigidbody spawnCard;
    7.  
    8.     void Start () {
    9.     }
    10.    
    11.     void OnGUI()
    12.     {
    13.         if (GUI.Button(new Rect(100, 300, 100, 100), "DealCard"))
    14.         {
    15.             Rigidbody newCardClone;
    16.             newCardClone =(Rigidbody)Instantiate(spawnCard,GameObject.Find("birthBall").transform.position, Quaternion.identity);
    17.  
    18.            
    19.             [COLOR="red"]cardVars myCardVars = newCardClone.GetComponent(typeof(cardVars)) as cardVars;
    20.             myCardVars.count = 33;
    21.             myCardVars.cardName = "IhazaFAIL";[/COLOR]
    22.         }
    23.     }
    24.    
    25.     void Update () {
    26.    
    27.     }
    28. }

    Runs fine,..click the button,..makes a newCard, although it appends the word 'clone' on everything, hence why I tried to use the name newCardClone when instantiating.
    BUT
    on mouse over none of my preFab's variables have changed. and I cry and rageQuit and go see Pirates:On Stranger Tides..and cry some more.

    I am not confident about the highlighted Red part at all, it's been most troublesome!
    Thank you all for reading this far, and any help will be most welcome!

    -Welby

    (the examples for this on the resource site confuses me even more!)

    PS: this is just a sample of something bigger I am making. I ultimately want to use this to generate a sort of playing card, each with it's own value( 1-10). Is instancing the way to go? or should I be looking for other ways.
     
  2. smurd

    smurd

    Joined:
    Sep 20, 2010
    Posts:
    2
    Hallo,

    try it that way:

    Code (csharp):
    1.  
    2. GameObject newCardClone;
    3. newCardClone =(GameObject)Instantiate(spawnCard,GameObject.Find("birthBall").transform.position, Quaternion.identity);
    4.  
     
  3. arzi

    arzi

    Joined:
    Apr 6, 2009
    Posts:
    154
    Check that your card prefab has both the Rigidbody and cardVars components. Otherwise I don't see anything wrong with that code. Though you might want to use GetComponent<cardVars> instead of casting.
     
  4. KodaL

    KodaL

    Joined:
    Apr 4, 2008
    Posts:
    37
    I've seen this before but don't understand the difference between GetComponent<cardVars> and the other way?
     
  5. SkaredCreations

    SkaredCreations

    Joined:
    Sep 29, 2010
    Posts:
    296
    If you use "GetComponent<cardVars>()" then you're explicitly specifying the type of the returned value, while "GetComponent("cardVars")" will need an explicit cast after the result has been returned. Of course the first way is more C# and OOP oriented and it's clearer (besides shorter in code).

    Code (csharp):
    1.  
    2. cardVars myComp = GetComponent<cardVars>();
    3. cardVars myComp = (cardVars)GetComponent("cardVars");
    4.  
     
  6. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    You can boil this down quite a bit and be more explicit at the same time.

    Your generator component doesn't deal with rigidbodies in general. It's supposed to deal with cards specifically. Your cards require rigidbodies, but that information is not something your generator component needs to worry about.

    Oh and another quick tip; upper-case the first letter in class names. It makes your code easier to read for both yourself and others.

    Given all of this, here is what I would do:

    CardVars.cs:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [RequireComponent (typeof (Rigidbody))]
    5. public class CardVars: MonoBehaviour
    6. {
    7.     public string cardName;
    8.     public int count;
    9.    
    10.  
    11.     public void OnMouseEnter ()
    12.     {
    13.         Debug.Log (" Name=  " + cardName);
    14.         Debug.Log (" Count=  " + count);
    15.     }
    16. }
    Generator.cs:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Generator : MonoBehaviour
    5. {
    6.     public CardVars cardPrefab;
    7.    
    8.  
    9.     void OnGUI ()
    10.     {
    11.         if (GUI.Button (new Rect (100, 300, 100, 100), "Deal card"))
    12.         {
    13.             CardVars newCard =(CardVars)Instantiate (cardPrefab, GameObject.Find("birthBall").transform.position, Quaternion.identity);
    14.  
    15.             newCard.count = 33;
    16.             newCard.cardName = newCard.gameObject.name = "IhazaFAIL";
    17.         }
    18.     }
    19. }
    Notice I also set the name of the GameObject of the newly spawned card. Sounds like you were looking for a way to do that.
     
  7. welby

    welby

    Joined:
    Mar 22, 2011
    Posts:
    549
    wow,..lotsa good sounding feedback,..I just got to work, but I will sneak this in sometime and try it out,...I will report back later with results,.thanks!

    -Welby
     
  8. welby

    welby

    Joined:
    Mar 22, 2011
    Posts:
    549
    UpDate: I rebuilt the scene from scratch at work using the exact same code from home, just as a start before I try out all your changes and it works now. So that will affect my responses below.

    Changing from RigidBody to GameObject still works,., but it Doesn't Break it at least,..he hee




    Oh they are all connected. But you know what. I came into work this morning and rebuild my scene here and you are right, the code is working!

    I wonder: since I was changing publics and what not WHILE the scripts were still attached, perhaps it wasn't internally updating itself, like remembering an old reference. And not until I rebuild from scratch the 'new' code will it work....hmmmm





    Amazing! thank you very much. Very insightful info.

    You mention about capitalizing class names, which makes perfect sense.

    In this case, you are using my script as a Class in the generator script. For this to work, I must make sure my script name is capitalized too so it matches. Is it normal practice to capitalize script names as well, for the reason of using them as Classes later?

    Again, thank you all for the responses. Next up for me is doing the array thing to 'store' this info for the different cards.

    /cheers
    -Welby
     
  9. AngryAnt

    AngryAnt

    Keyboard Operator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
    Usually people capitalize class name and have those match the name of the file containing the classes, yes.
     
  10. Second Chance

    Second Chance

    Joined:
    Jul 9, 2009
    Posts:
    22
    I'm so glad I found this thread (search is a wonderful thing). I've been having a terrible time trying to instantiate a prefab into a variable in C#. I kept getting casting errors no matter what I tried. So finally I decided to just paste the code from the C# Instantiate docs into a script and see if it would lead me to why I had errors.

    Interestingly, the code from the C# documentation is erroneous. Both of these example code blocks:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class example : MonoBehaviour {
    5.  
    6.    public Transform explosion;
    7.  
    8.    void OnCollisionEnter() {
    9.       Destroy(gameObject);
    10.       Transform theClonedExplosion;
    11.       theClonedExplosion = Instantiate(explosion, transform.position, transform.rotation);
    12.    }
    13. }
    and

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class example : MonoBehaviour {
    5.  
    6.    public Rigidbody projectile;
    7.  
    8.    void Update() {
    9.       if (Input.GetButtonDown("Fire1")) {
    10.          Rigidbody clone;
    11.          clone = Instantiate(projectile, transform.position, transform.rotation);
    12.          clone.velocity = transform.TransformDirection(Vector3.forward * 10);
    13.       }
    14.    }
    15. }
    Produce this type of casting error...
    ...in Visual Studio.

    Now I see that you can't just call Instantiate(something, vec3, quat) while assigning to a variable, you have to call (SomeClass)Instantiate(something, vec3, quat). If this is indeed the answer, I can finally stop banging my head on the desk, yay!

    Anyone know how to report this, so we can get the docs updated?
     
  11. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    The bug reporter has a "Documentation" selection.

    --Eric
     
  12. Second Chance

    Second Chance

    Joined:
    Jul 9, 2009
    Posts:
    22
    Ah ha, thank you :)