Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug [SerializeField] not working right?

Discussion in 'Scripting' started by karsten-heim, Aug 5, 2022.

  1. karsten-heim

    karsten-heim

    Joined:
    May 16, 2022
    Posts:
    63
    I have two scripts that use [SerializeField] to make private variables viewable, but I added some new stuff, and that made me get this warning:

    Assets/SceneController.cs(13,6): error CS0616: 'SerializeField' is not an attribute class

    I did not have this problem before, so I undid all of my work, and the issue still persisted, even though that script worked earlier. I have an older version of unity, but I do not think that this is the problem.
    here are the places I utilize [SerializeField]

    [SerializeField] private GameObject backofcard;
    [SerializeField] private Sprite imagee;
    [SerializeField] private clickers originalCard;
    [SerializeField] private Sprite[] images;

    I have no idea why this would happen, but I have isolated it so that it is not my script, so I don't know what to do from here.

    Here is the script in question in case I did something wrong while spamming ctrl + z
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class clickers : MonoBehaviour
    6. {
    7.     [SerializeField] private GameObject backofcard;
    8.     [SerializeField] private Sprite imagee;
    9.     private int id_;
    10.     public int id
    11.     {
    12.         get { return _id; }
    13.     }
    14.     public void SetCard(int id, Sprite imagee)
    15.     {
    16.         _id = id;
    17.         GetComponent<SpriteRenderer>().sprite = imagee;
    18.     }
    19.     public void OnMouseDown()
    20.     {
    21.         //Debug.Log("clicked");
    22.         if (backofcard.activeSelf)
    23.         {
    24.             backofcard.SetActive(false);
    25.         }
    26.  
    27.  
    28.     }
    29. }
    30.  
    also I know this isnt the scenecontroller script, the issue is in both scripts independent of one another
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,519
    Your SetCard() accepts two arguments that are named identically to your class instance field / property.

    While legal, that's not likely a good strategy for success.

    Not only that but you have
    _id
    and
    id_
    so this code doesn't even compile.

    You might want to just go nice and simple, make everything public, avoid all the fancy-schmancy OO classroom getters / setters until it all works, then go turn the code into something that the computer science majors would approve of, if that's a thing you even want / need (I don't recommend anything except the barest of simplicity).

    In any case, this ALWAYS applies:

    Remember: NOBODY here memorizes error codes. That's not a thing. The error code is absolutely the least useful part of the error. It serves no purpose at all. Forget the error code. Put it out of your mind.

    The complete error message contains everything you need to know to fix the error yourself.

    The important parts of the error message are:

    - the description of the error itself (google this; you are NEVER the first one!)
    - the file it occurred in (critical!)
    - the line number and character position (the two numbers in parentheses)
    - also possibly useful is the stack trace (all the lines of text in the lower console window)

    Always start with the FIRST error in the console window, as sometimes that error causes or compounds some or all of the subsequent errors. Often the error will be immediately prior to the indicated line, so make sure to check there as well.

    All of that information is in the actual error message and you must pay attention to it. Learn how to identify it instantly so you don't have to stop your progress and fiddle around with the forum.
     
    Last edited: Aug 5, 2022
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    Well, I hate to say this, but your script above is named "clickers" and the error points to SceneController.

    Assets/SceneController.cs(13,6): error CS0616: 'SerializeField' is not an attribute class

    So, "clickers" is probably not the problem script. Post the other script.
     
    mopthrow likes this.
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    20,954
    If you're only using properties to restrict how the variable is accessed there is a shorter form available. The following property is read only outside of the class, but can be read and written to inside it.
    Code (csharp):
    1. public int id { private set; get; }
    With that you can access the property by its name without having to remember the underlying variable.
    Code (csharp):
    1. public void SetCard(int id, Sprite imagee)
    2. {
    3.     this.id = id;
    4.     GetComponent<SpriteRenderer>().sprite = imagee;
    5. }
     
    Last edited: Aug 5, 2022
  5. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Well, this error tells us all we need to know. You created your own type named SerializeField somewhere in your project inside the global namespace. So you're hiding the one in the UnityEngine namespace. The global namespace always has precedence. I would highly suggest to rename your own type to something else.

    If you don't know where that type is or where it may came from, just use a proper IDE like visual studio, right click on SerializeField and choose "Go To Definition". It should bring you right to the point where that "wrong" class / struct / type is defined. If it comes from an external package, I would try to get rid of it ^^. If the type actually was in a namespace, you would get an ambigous reference error instead as the compiler can't tell which type you want to use.

    If the type came from a framework / library / package you really have to use, the only alternative is to either add

    Code (CSharp):
    1. using SerializeField = UnityEngine.SerializeField;
    At the top of every Unity script where you used SerializeField, or replace all
    [SerializeField]
    with
    [UnityEngine.SerializeField]
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Note: If you managed to mess up your namespaces by introducing a sub-namespace with the same name as a top level namespace, you may want to have a look at the :: operator and the single most important alias in C#:
    global
    . The global alias allows you to actually query a full namespace by actually starting at the global namespace. This operator can also be useful in some cases if you have complex and long namespaces so you can define an alias name. However I highly recommend to keep that usage to a minimum. Using fancy alias names just makes it harder to read the code.
     
  7. karsten-heim

    karsten-heim

    Joined:
    May 16, 2022
    Posts:
    63
    thanks for the help, i looked at the definition of it, and apparently i have an old script named SerializedField that I dont remember creating, and apparently it was using that, which i guess makes it a class, not an attribute.
     
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,919
    Attributes are just classes as well. Though, as the error tells you, attribute classes have to be derived from the special
    System.Attribute
    class.

    Note that within the same namespace any type name must only exist once. It doesn't matter if that type is a class, struct, enum, delegate or interface. Those are all different kinds of types but the names must not overlap. So as an example, Unity has the Random class inside the UnityEngine namespace. If you create an enum like this

    Code (CSharp):
    1. public enum Random
    2. {
    3.     Foo,
    4.     Bar
    5. }
    It would also clash with the Random class. So when you try to use
    Random.Range(1,42)
    you would get an error that the enum Random does not contain something called "Range". If that enum is defined in a seperate namespace:

    Code (CSharp):
    1.  
    2. namespace B83.MyBadlyNamedEnums
    3. {
    4.     public enum Random
    5.     {
    6.         Foo,
    7.         Bar
    8.     }
    9. }
    this would mitigate the issue. Though when you import both namespaces inside the same file

    Code (CSharp):
    1. using UnityEngine;
    2. using B83.MyBadlyNamedEnums;
    3.  
    4. // [ ... ]
    You would get an ambiguous name error from the compiler when you try to use "Random" in that class since it's not clear what type you want to use. As I said, things defined in the global namespace (so when the type is not defined in an explicit namespace) have a higher priority than things in a namespace.