Search Unity

Creating an array of references to another array

Discussion in 'Scripting' started by arcandio, Sep 10, 2012.

  1. arcandio

    arcandio

    Joined:
    Aug 30, 2009
    Posts:
    89
    This last week has been my week for coding issues.

    Today's topic: references to the same object in an array.

    In part of my code, I set up an array of characters. In a different part of my code, I generate an array of pages, and each page has a character associated with it. I want my pages to refer to the instance of the character in the list, so that many pages might refer to the exact same character. This way, if I change the character in the character array, it changes the character on all pages as well. Right now I'm just doing it like so:
    Code (csharp):
    1.  
    2. page.character = characterArray[0];
    3.  
    but it seems to create an instance of that character for each page that uses it. (I do convert the array of pages to a builtin array eventually, after generating them all. Could that cause this?)

    Any idea how to maintain the references to the original objects across several assignments?

    ps: my code is like 700 lines and embedded in the middle of a complicated addon project, so it's not easy to paste the whole example in here.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Assignment usually doesn't duplicate reference type objects.

    What is a 'Character' and what is a 'Page'??? Are they classes? Are they structs?

    In C# if I say:

    Code (csharp):
    1.  
    2. var objA = new MySpecialType();
    3. var objB = objA;
    4. Debug.Log(objA == objB); //returns true
    5.  
    note, objA and objB are the SAME OBJECT, just different references.

    So... what and how are you "assigning" these objects that it's getting duped?
     
  3. arcandio

    arcandio

    Joined:
    Aug 30, 2009
    Posts:
    89
    they're both classes in javascript.

    I'm paraphrasing:

    Code (csharp):
    1.  
    2. class Character
    3. {
    4.     var color : Color = Color.white;
    5.     //some other vars
    6. }
    7. class Page
    8. {
    9.     char : Character;
    10.     //some other vars
    11. }
    12.  
    13. var characters : Character[]; //set up in the editor
    14. var pages: Page[]; //generated by an editor script
    15. var tempPageArray : Array = new Array();
    16. //generate pages from text in a for loop
    17. for(/*each page from parsed text*/){
    18.     var newPage : Page = new Page();
    19.     newPage.char = characters[0];
    20.     tempPageArray.Add(newPage);
    21. }
    22. //after page generation for loop
    23. pages = tempPageArray.ToBuiltin(Page); //does this break my references or something?
    24.  
    then after that point, when I set pages[3].char.color to Color.red, and access pages[4].char.color, it's still Color.white, even though the character for pages[3] and pages[4] are supposed to be the same. Likewise, when I edit the original instance, characters[n] or whatever, that change doesn't trickle down to the references on each page.

    Sorry if I'm being super-obscure, I don't have the code available at the moment.
     
  4. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Have you considered scaling back some of the complexities and building up from there?

    Maybe just create two dummy classes with said props, and fill them with dummy data (not parsed fromtext files and editor panels). And attempt to replicate the problem.

    If it does, start adding the parts in and see where you may have gone wrong. If it doesn't, scale back further until it does. Replace parts... etc.


    I don't know how unity's javascript compiles into CIL, so I'm not sure how Array.ToBuiltin works, so I couldn't tell ya what's up there. Try using List<Page> or go with C# and try again. Furthermore I don't know how it handles classes... it might turn simple classes into structs for efficiency sake and that's hurting you...



    edit:

    I just tested with this, and everything work as expected... Something is going wrong in all the left out stuff from your code.

    Code (csharp):
    1.  
    2. class Character
    3. {
    4.     var color:Color = Color.white;
    5. }
    6.  
    7. class Page
    8. {
    9.     var char:Character;
    10. }
    11.  
    12. function Start () {
    13.  
    14.     var chars = new Array(new Character());
    15.     var pages:Page[];
    16.  
    17.     var tempPageArray:Array = new Array();
    18.  
    19.     for(var i:int = 0; i < 10; i++)
    20.     {
    21.         var newPage:Page = new Page();
    22.         newPage.char = chars[0];
    23.         tempPageArray.Add(newPage);
    24.     }
    25.  
    26.     pages = tempPageArray.ToBuiltin(Page);
    27.  
    28.     pages[0].char.color = Color.red;
    29.  
    30.     Debug.Log(pages[0].char.color);
    31.     Debug.Log(pages[1].char.color);
    32.  
    33. }
    34.  
     
    Last edited: Sep 10, 2012
  5. arcandio

    arcandio

    Joined:
    Aug 30, 2009
    Posts:
    89
    I'm not sure why it worked, but I changed the assignment of pages from Array.Add() to Array.length +=1 and then assigned the character to the last page. Weird. The other thing I noticed, was that the editor itself was acting kinda weird with how it dealt with assigning these things.

    Code (csharp):
    1.  
    2. #pragma strict
    3. var thingList : thingClass[];
    4. var thingInstance : thingClass;
    5. var thingArrayCast : thingClass[];
    6.  
    7. class thingClass {
    8.     var f : float = 0;
    9. }
    10.  
    11. function OnDrawGizmos () {
    12.     thingInstance = thingList[0];
    13.     var tempArray : Array = new Array();
    14.     tempArray.Add(thingList[0]);
    15.     tempArray.Add(thingList[0]);
    16.     tempArray.Add(thingList[0]);
    17.     var tempObj : thingClass = tempArray[0] as thingClass;
    18.     Debug.Log(tempObj.f);
    19.     thingArrayCast = tempArray.ToBuiltin(thingClass);
    20.     thingList[0].f = 7777;
    21. }
    22.  
    in this example, I could only change the value of the thingArrayCast[0] instance, but it would in fact change all the other references. If I tried to change the original, thingList[0], the editor would change the number back immediately upon commiting my change to the field. But that last line, 19, came off without a hitch, changing thingList[0] and then that would cache down to everything else.

    Anyway, I have a solution, involving not using Array.Add(), which seems to work fine. If it breaks from here, at least I can just use the Array type and manually output the results in the editor. Thanks for the help!