Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question Can't figure out how to call this method in class script

Discussion in 'Scripting' started by Slaghton, May 10, 2024.

  1. Slaghton

    Slaghton

    Joined:
    Sep 9, 2013
    Posts:
    145
    So I removed a lot of the code from this asset but should be enough to get the idea. So this MapData script is a class that I am supposed to talk to to save some data, and being mostly an artist myself, I don't know the proper way to call Save() from say my player char. I try doing something like MapData.Save("test") it complains about it not being static and if I try the static save method idk what to put to call it, like MapData.Save("test", ???).

    I did try Mapdata mapdata_ref; at the top and below tried mapdata_ref("test"); but that threw an error part way through like it was missing some data. Don't think that's the correct way to do it anyway though.

    Can anyone point me in the right direction? Pretty sure this should be easy but been stuck on it for about 3 hours now.


    Code (CSharp):
    1. namespace MapMinimap
    2. {
    3.     /// <summary>
    4.     /// Map data that is saved
    5.     /// </summary>
    6.  
    7.     [System.Serializable]
    8.     public class MapData
    9.     {
    10.         private static string file_loaded = "";
    11.  
    12.  
    13.  
    14.         // --- Save/load/new --------
    15.  
    16.         public void Save(string test)
    17.         {
    18.             file_loaded = test;
    19.             Save(file_loaded, this);
    20.         }
    21.  
    22.         public static void Save(string filename, MapData data)
    23.         {
    24.             if (!string.IsNullOrEmpty(filename) && data != null)
    25.             {
    26.              //Removed code
    27.             }
    28.         }
    29.     }
    30. }
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,213
    MapData.Save("test") is not accessible because you're trying to access it as if it were a static method, but you haven't declared it as such, it's just an ordinary instance-based (non-static) method.

    To be able to do that, you need to declare
    Code (csharp):
    1. public static void Save(string test) {
    2. ...
    Edit:
    Oh, and the other static method 'Save' that you did declare has a wrong argument signature (or maybe I didn't quite get what you meant by the latter part of your post, the code you showed is incompatible with what you described).

    All in all I think you're having a hard time understanding these concepts, so you should probably ask whatever is confusing you about static and non-static data.
     
    Last edited: May 11, 2024
    spiney199 likes this.
  3. Slaghton

    Slaghton

    Joined:
    Sep 9, 2013
    Posts:
    145
    Thanks for the reply Orion!

    *Just a heads up, this code is from an asset from the store so i'm trying to make sense of the code :x*

    (Oh, if I change that non static function to static, then the line 19 below doesn't work anymore).
    Save(file_loaded, this);

    Think i'll just cut my losses and grab a different asset from store.

    The part that's tripping me up is there's 2 save methods in that class script. It appears that the non static void method triggers the static save method, so it seems I should be firing the non static save method but I don't think that's possible?

    Maybe the code is incomplete and author wants you to buy the bundle that states save feature since the map addon doesn't. I'm betting this is the case since I wasn't able to get much help from the discord either.

    There's another asset with the feature i was looking for that isn't bundled up with other things so I think i'll just grab that off the store.
     
    Last edited: May 11, 2024
  4. Ryiah

    Ryiah

    Joined:
    Oct 11, 2012
    Posts:
    21,679
    It's just a shortcut method. It's likely for the author rather than for the user.
     
  5. Slaghton

    Slaghton

    Joined:
    Sep 9, 2013
    Posts:
    145
    I see, is it possible to call the static void method below without the top part? Issue there is i'm not sure how to populate the MapData parameter without passing it from the non static save method.

    Code (CSharp):
    1.         public static void Save(string filename, MapData data)
    2.         {
    3.             if (!string.IsNullOrEmpty(filename) && data != null)
    4.             {
    5.              //Removed code
    6.             }
    7.         }

    I've done it in a very hacky and wrong way by trying this, which will cause it to work, but it ends up being kinda buggy. It seems like the author was saying all you had to do was MapData.save("string"); but.. yeah idk. I guess I don't have much experience using class scripts/static variables

    Code (CSharp):
    1. MapData mapdataref;
    2.  
    3. mapdataref.save("test");
     
  6. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,213
    The static method is what actually does the job. It requires the file name and the actual instance reference.
    The other, non-static method is when you already handle the instance locally, you call it on the instance, and it internally redirects the call by passing
    this
    (a special C# keyword) as the instance reference.

    So, for example
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class Example : MonoBehaviour {
    4.  
    5.   [SerializeField] MapData _myMapData;
    6.  
    7. }
    You use this to hook MapData in editor by drag'n'drop.
    When deserialized,
    _myMapData
    will hold onto that object in memory.
    Now somewhere in that script you decide to call Save method on that instance
    Code (csharp):
    1. void doSave(string name) {
    2.   _myMapData.Save(name);
    3. }
    Internally, it'll call the static
    MapData.Save(string filename, MapData data)
    where data is set to _myMapData reference. Frankly, it couldn't be any simpler.

    Edit:
    Alternatively (for completeness), you can do
    Code (csharp):
    1. void doSave(string name) {
    2.   MapData.Save(name, _myMapData);
    3. }
    Which does the same thing, the other way is merely a convenience.
     
    Last edited: May 11, 2024
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,213
    Btw you really ought to learn more about these concepts. There can be only one static definition (because there is only one such class), but zero-to-many object instances of that class. Each instance (and any other code elsewhere if you don't mind weird dependencies) can always access the static data, but the vice versa doesn't hold true. This is because the static data is strictly accessible through the class name, whereas instance data requires a runtime reference (because it's a runtime-only object) which you need to keep somewhere in a variable.
     
    Last edited: May 11, 2024
  8. Slaghton

    Slaghton

    Joined:
    Sep 9, 2013
    Posts:
    145
    Oh wait, this looks like what I tried earlier but I thought it was wrong because it sprouted errors which I spent hours trying to debug what exactly was failing in the code.

    (Again, appreciate the replies from you two!) Looking over it again, but I think I actually did this earlier today.

    Update: Yeah, there is no error's in firing the save code discussed with what you said, its something further in not working (attempted this earlier). I got around the errors by also trying to fill in variables that I believe I shouldn't have to since author said I just had to call save method but it errors out if I just leave it be. That's why it felt like it was incomplete. I did get it partially working, but it did require more then just calling the save() method.

    Authors Note: You just need to call the Save() function using MapData.
     
    Last edited: May 11, 2024
  9. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,213
    Btw, if you're not well-versed with the static stuff, it's worth noting that static fields and methods are powerful if used correctly, just don't use them as a crutch for easy access to your code or data. Sometimes you can get away with it, but more often than not, it'll turn into ugly spaghetti and a very great headache.

    Static methods are incredibly useful for writing stateless and general code, pure functions, top-down utilities and tools and such. Additionally the class itself can be made static as well so that it doesn't support instantiation at all. In this particular case having instances is allowed (the class is not static), but the instances do not actually hold anything by themselves. Still you can keep several maps separated and you can call Save on each of them, so this differentiation matters.

    This comment is not intended as a criticism of that asset store thingy, more of a general advice, because newbies usually think it's a neat hack to have everything everywhere (it is not, just do not fall in this trap). I'd say the author uses it properly: the MapData class does one general thing (for which a static method is perfect, because it does not necessitate an encapsulated instance state) and then provides an API to access this one thing more conveniently or more intuitively, in line with how he foresaw the intended usage pattern.

    I can't however definitively say whether this is a good asset or not, because I can't see the rest of the code, so if you can find something that works just as well, but you can understand it better, go with that.
     
    Slaghton likes this.
  10. Slaghton

    Slaghton

    Joined:
    Sep 9, 2013
    Posts:
    145
    Thanks for the info orion! I've barely touched static variables since I haven't found too much of a reason to yet so I got really tripped up with this lol. With instancing, I have a bit more experience since my players skin/hair materials are all instanced from 1 material so I can change the properties to allow for visual customization and stuff.

    I have zero knowledge in using class scripts though, never made one in the 14 years i've been using unity haha. Guess it wouldn't hurt to finally learn about them, so far i've gotten away without using them. Creating a class scripts feel like a way to organize your scripts/code so you don't have 1 giant script with a lot of your code in it. Not sure if that's correct though, I started off as a 3d artist and been learning coding as I go along.

    o7!

    p.s. Everything but that save feature works in the asset im using (which saving this particular data isn't actually necessary for my game, I just got invested in trying to make it work heh). I don't feel like the code is bad or anything, maybe a little different.
     
    Last edited: May 11, 2024
    orionsyndrome likes this.
  11. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,213
    Well you can definitely start from that definition, it's not bad, however it's not just for the practical organization, it's also deeply semantical due to how object oriented paradigm is designed.

    Also as our projects (games) get larger and larger, there is quite a lot of infrastructural logic depending on how the codebase is actually organized (aka the software architecture) and it can get VERY COMPLEX. Such complexity renders any simple shortcuts (such as the static abuse I explained earlier) useless or counterproductive in the long run.

    But if you're a beginner, you'll learn from mistakes, there is no other way.
    And if you keep your projects simple enough, you'll be fine.
     
    Slaghton likes this.