Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by jessee03 · Oct 21, 2013 at 09:31 AM · arraylist

List changes affecting Array

So currently I have an Array and a List. Items from the Array are added to my List. The problem I'm having is when I subtract from the List it affects the original number in the Array.

Example: myList[x].number -= 1;

Which causes myArray[0].number to also minus 1.

Do I need to make some variable private? Or I am not sure.

Comment
Add comment · Show 8
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image vexe · Oct 21, 2013 at 09:40 AM 0
Share

Why do you need to do this? Either store them in the list, or the array in the first place.

Items from the Array are added to my List

How are you doing the add? It seems to me that they're both referencing the same thing.

avatar image jessee03 · Oct 21, 2013 at 09:54 AM 0
Share

I am working with debuffs that are being added to a list. So I can add multiples as much as I want and remove as needed. This way they can also be displayed properly how I want and each have separate timers for when to remove them.

How you would normally add to a List from an Array debuffList.Add(debuff[0]);

avatar image vexe · Oct 21, 2013 at 09:57 AM 0
Share

whats a debuff? a value type? (int/float?)

avatar image jessee03 · Oct 21, 2013 at 10:01 AM 0
Share

The value is a float. debuff is the Array which stores each of the different debuffs that are added to the List.

avatar image ArkaneX · Oct 21, 2013 at 10:49 AM 2
Share

@vexe is right - elements in your array and list are referencing the same objects in memory. Subtracting from a variable number in one of these debuff object stored in a list, results in lowering this value in element of array as well. To handle this properly, you can clone an object from the array, and add this clone to the list. For example:

 var clone = new Debuff(); // type of debuf stored in array
 clone.number = debuff[0].number;
 clone.otherVariable = debuff[0].otherVariable;
 debuffList.Add(clone);

You can encapsulate this cloning logic into some constructor or static method.

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
4

Answer by Azrapse · Oct 21, 2013 at 10:46 AM

You have to read something about Reference Types as opposed to Value Types. I will try to give you a quick hint.

In C# and most languages, the types can be either reference types or value types. The main difference is where the values of the objects are 'stored'.

In a value type, for example int or float, the value itself is stored in the variable. In a reference type, the objects are stored somewhere in memory, and variables just hold a reference to the object, a pointer, an address.

For example, you have something like this:

 struct myValueTypeFriend{
     string Name;
     string Phone;
 }
 myValueTypeFriend a = new myValueTypeFriend{Name = "David", Phone="12345"};
 myValueTypeFriend b = a;
 a.Phone = "555666";
 // b.Phone still is "12345";

That is because the values are stored in the variables, and when you use = to assign the value of one variable to another, what your are doing is making a copy of the value. Essentially cloning it. So that is why after copying the friend from a to b, if a modifies one of the fields or properties, that doesn't affect the clone that b got before.

However check this example now:

 class myReferenceTypeFriend{
     string Name;
     string Phone;
 }
 myReferenceTypeFriend a = new myReferenceTypeFriend{Name = "David", Phone="12345"};
 myReferenceTypeFriend b = a;
 a.Phone = "555666";
 // b.Phone is now "555666";

That happens because a and b are now reference type variables. If you assign the value of one reference type variable to another, what you are doing is making another variable point to the same object the first variable is pointing, so any change to the object will be visible for both variables.

As you see, if you create a class, objects of that class will be reference type objects. If you create a struct, objects of that struct will be value type objects.

What is happening in your example is that you have a List<Debuff> myList and a Debuff[] myArray.

I bet you have defined Debuff as a class that has, among other things, a member called number of float type. Right?

When you add a Debuff object to the list, you are just adding a pointer to the real Debuff object, that is somewhere in memory. When you copy that item from the list to the array (or viceversa), you are just copying the pointer, the reference. So when you access myList[0].number and myArray[0].number, you are accessing the same object and the same field (if indeed both first elements are the same).

You have two alternatives.

First: When you add the Debuff from the array to the list, you must make a clone of it. For that, you could add a Clone() method to the Debuff class that creates a new Debuff object and copies the values of every field from the original to the new one. I recommend you checking this link.

Second: Change Debuff so that it's a struct instead of a class. However beware, structs cannot inherit from other structs or classes (only interfaces). If your Debuff is making heavy use of inheritance you will have to use the other alternative. Also, if your Debuff contains members (fields) that are of reference type, you will encounter the same problem. Read the link above for more information. In C# use

 struct Debuff
 {
     //code
 }

In UnityScript, use

 class Debuff extends System.ValueType
 {
     //code
 }

if it doesn't support the struct keyword.

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jessee03 · Oct 21, 2013 at 11:12 AM 0
Share

I guess I could of made it easier by posting my code.

//Debuff Class

 class Debuff {
 
     var debuffName : String;
     var debuffTime : float;
     var debuffIcon : Texture2D;
 
 }

//Script

var debuff : Debuff[];

var debuffList : List. = new List.();

function Start () {

 InvokeRepeating("debuffTimer", .01, 1.0);    
 debuffList.Add(debuff[0]);

}

function Update () {

     //Test adding Debuffs to List
     if(Input.Get$$anonymous$$eyDown("g")) {
 
     debuffList.Add(debuff[0]);    
 }

}

function debuffTimer () {

 for(var i = 0; i < debuffList.Count; i++) {
 
     debuffList[i].debuffTime -= 1;
     
     if(debuffList[i].debuffTime <= 0) {
     
         debuffList.RemoveAt(i);        
     }    
 }

}

avatar image Azrapse · Oct 21, 2013 at 11:16 AM 0
Share

Try changing Debuff from being a class to be a struct. It think it is okay that the field debuffIcon, of type Texture2D, stays being a reference. You don't want to duplicate the icon textures really.

Not sure if UnityScript supports the struct keyword, though. If not, try this

 class Debuff extends System.ValueType
 {
     //code
 }
avatar image vexe · Oct 21, 2013 at 11:16 AM 0
Share

This should be added as an edit to your question. the problem is clear now, with the knowledge from both the two answers ^ and Arkane's comment, you should be able to solve the problem.

avatar image CHPedersen · Oct 21, 2013 at 11:19 AM 0
Share

The struct keyword is fully supported, and a struct may contain reference type members.

You must still beware the distinction between value type and reference type, of course. If you change the above to structs, you'll get copies of the values of struct Debuff, but these values would then contain copies of the references to Texture2D. If this is okay, you're fine.

avatar image vexe · Oct 21, 2013 at 11:19 AM 0
Share

you could also create a copy constructor, and add your elements like myList.Add(new Debuf(arr[INDEX]); - that would copy the whole thing over.

In c#, it would look like:

 class Debuf
 {
   public string debufName;
   public float debufTime;
   public Texture2D debufIcon;
 
   public Debuf(Debuf d)
   {
     debufName = d.debufName;
     debufTime = d.debufTime;
     debufIcon = d.debufIcon;
   }
 }

But notice here, the Texture2D is a ref type, so even the new debuf is pointing to the one in your array, just be aware of that.

Show more comments
avatar image
2

Answer by CHPedersen · Oct 21, 2013 at 10:43 AM

This is likely because the items stored in your array and list are both reference type variables. The difference between reference types and value types is an important one, and every programmer would be well advised to study this concept well.

In very short summary, and specific to your situation:

If you have reference types in both the List and the Array, then the references will point to the same actual object, i.e. you're not storing two copies of the object, you're storing two references to them. Consider the following example:

You have a house. The house has 4 doors.

You take the street address to your house and store it in the List. Then you take the same address and store it in the Array.

Now, go to the address stored in the List. Remove a door from the house at that address. It now has 3 doors.

Does the house at the address stored in the Array still have 4 doors?

No, 'cause it's the same house. ;)

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image vexe · Oct 21, 2013 at 10:47 AM 0
Share

That's what I had in $$anonymous$$d first, which is why I asked him about the debuf, which turned out to be just a float (value-type)

avatar image CHPedersen · Oct 21, 2013 at 10:50 AM 0
Share

I got that. But I don't think he's storing the floats. I think the debuff is a member of an object, and he's storing the objects. Hence the access to ".number" in his code sample. But we'd need to see more code to be sure.

avatar image vexe · Oct 21, 2013 at 10:51 AM 0
Share

he needs to state the type of debuff clearly, and give more info.

avatar image jessee03 · Oct 21, 2013 at 11:14 AM 0
Share

Posted my code in Azrapse's answer.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

20 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

A node in a childnode? 1 Answer

Changes not being saved in the Inspector Editor 1 Answer

Keep adding targets to a list 2 Answers

Difference between Static, Dynamic, and Built-In Arrays 1 Answer

Adding and Removing to a Inbuild Array 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges