0

Alight, I apologize that this will be a rather dumb question, but I am trying to gain a full understanding of the purpose and use of objects. Specifically I am working in Unity, but I am not sure that this matters. Also, I should also mention that the language is rather overwhelming. But here is the simple example that I am working on.

public class Player : MonoBehaviour 
{
    private string name = "Players Name";

    private void Start () {
        var nexus = new Player();
    }

    public static void Using() {
        // how are these different?
        Attack();
        this.Attack();
    }

    public static void Move() {
        print ("The player is moving"); 
    }

    private void Attack () {
        print ("The player is attacking"); 
    }
}

public class UsingStuff : MonoBehaviour 
{
    private void Start () {
        Player.Move();
    }
}

So here are the questions:

  1. What is the difference between calling a function Attack() versus this.Attack? From a novice perspective, they would seem to do exactly the same thing. However, I am assuming that my example is just too simplistic.
  2. I created the object of the Player class with the random name nexus. However, when I call a function from a different class I seem to use the class name rather than this variable name. So what is the purpose of creating a variable name?

I will leave it at those two for now, as hopefully that will help with some confusion for some other things. Thank you for your help.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
shodai
  • 113
  • 2
  • 11
  • 1
    1) There is no difference in this case. 2) You need a fundamental understanding of variables, properties, and scope. You should have a `Player` class member that you instantiate in `Start()`. Instead, you're creating a player and then throwing it away because it goes out of scope when `Start()` returns. – itsme86 Aug 08 '18 at 21:42
  • 1
    For #2, look at [C# static vs instance methods](https://hackernoon.com/c-static-vs-instance-classes-and-methods-50fe8987b231) to learn why sometimes you need an instance of a class (the variable name) to call a method, and other times you just use the class name (for static methods). – Rufus L Aug 08 '18 at 21:48
  • You should have the `Update` function it it's not in use, it's worse on preformance. Also, you shouldn't include it in the Stack Overflow post as it's not relavent to your issue. – AustinWBryan Aug 09 '18 at 05:07
  • 1
    I suggest you take a good amount of time to study C# and core programming concepts by themself before trying to make a game. It took me quite a while before I finally was ready for a game. Right now, you're learning to very complex things at once and that's hindering your learning of both things. – AustinWBryan Aug 09 '18 at 05:12

8 Answers8

3

What is the difference between calling a function Attack() versus this.Attack?

When you are coding the class Player for example and you want to use the method "Attack()" you can do that by typing Attack() or this.Attack(). It does the same thing in both cases.

When you use "this." you guarantee that the method you are using is the implemented on the class you are on. For example:

public void GroupAttack(DifferentPlayer ally){
    Attack(); 
    ally.Attack();
}

public void GroupAttackWithThis(DifferentPlayer ally){
    this.Attack(); 
    ally.Attack();
}

There is no difference between the method GroupAttack and GroupAttackWithThis.

Useful link to see the difference: In Java, what is the difference between this.method() and method()?

I created the object of the Player class with the random name nexus. However, when I call a function from a different class I seem to use the class name rather than this variable name. So what is the purpose of creating a variable name?

It happens because you made the function "Move" static, it means that for every instance of that class it will do exactly the same. Static is used when you want a method or a variable to have the same value or have a behavior identical every time for every instance of the class. If your method is not static you will need to use the name of the variable to use it, that is because you will want your method to change his behavior for every instance. A simple example:

public string GetName(){
    return name;
}

This method will return for every Player a different name (will return the name of the player in the variable). So if you do:

Player jhon = new Player();
jhon.name = "Jhon";
String jhonsName = jhon.GetName();

The variable "jhonsName" will contain a string with the value "Jhon".

I hope this could be useful for you and good luck with your game.

2

When you execute Player nexus = new Player();, you are creating a new instance (/object) of type (/class) "Player". The variable nexus is an object reference (i.e., it refers to the object instance you just created). Once you have an instance, you can call instance methods on that object, set or read its properties (which, by the way, you have none of). Since there is only one reference to that object (the nexus variable), when that reference goes out of scope (at the end of the function), the object no longer is referenced by anything and is eligible for garbage collection.

When you declare a method (/function) with the static keyword, you are creating it at the class level, rather than at the instance level. If you wanted to call the non-static Update or Attack methods, you'd have to say nexus.Update or nexus.Attack. To call the static Using or Move methods, you'd use the class name (Player) like this: Player.Using or Player.Move.

The code you posted does not compile, does it? You can't call an instance method from a static method. You can't call the instance method Attack or this.Attack from the static method Using (there's no "this" there (this is the current object instance associated with an instance method)). It's best to post code that at least compiles (unless you say (in a comment) //this is the code that doesn't compile

You also only create a new Player instance in the Start method, which is a little odd. Generally, you create instances of objects in other classes or in static factory methods (not always, but generally).

Read up on the nature of object oriented programming, on C#'s static keyword and on the nature of object instances (in general). You probably want to read up on C#'s properties as well.

Oh, and naming something Using is going to hurt in the long run (lower case using is a C# keyword that already has two meanings).

Finally, to answer your question, "calling an instance method this way: Attack() or that way: this.Attack() has the same semantics." Of course, as noted above, you can't use either form if you are trying to call an instance method from a static method.

Flydog57
  • 6,851
  • 2
  • 17
  • 18
2

There are some differences between Unitys MonoBehaviour to the normal C# classes. I recommend to watch some Unity Tutorials. Unity-Scripts are Scene oriented.

  1. There is no difference. this.Something can be used to mark something as "from the class object" (Normally Properties or Variables) to distinguish from parameters.

  2. Writing Player nexus = new Player(); should be a Warning because you should not do this with a MonoBehaviour.

You create a Player in the Scene by putting the Script "Player" on a GameObject. You should access the Player script from the GameObject. So you should remove "static" on the methods. Then put public Player player; inside UsingStuff (under public class UsingStuff : MonoBehaviour {). Then Drag your Player on the placeholder for Player. You will find it on the GameObject with the UsingStuff-Script in the scene. Now you can call player.Move() (with small p) in the Start Method.

Try another naming for your variable name. It already exist for every MonoBehaviour. It refers to the name of the GameObject the Script is lying on. Your naming should also throw a Warning.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
1
  1. The this keyword means "A reference to the current instance of the class" It's syntactic sugar really (it can make your code clearer to read)

When you do

public static void Using() {
    Attack();
    this.Attack();
}

Behind the scenes, the compiler will execute it as so:

public static void Using() {
    this.Attack();
    this.Attack();
}

so in your context, they are the same.

There are times it is useful see this post

  1. If I understand correctly, this question relates to why do you need to have a variable called name rather than just naming the object as the player name. The variable "name" and the name of the object are two different things

Lets say you want to output the players name to the screen

void Start () {
    Player nexus = new Player();

}

in the method above, i can't [simply] do it

void Start () {
    Player p = new Player();
    p.name = "nexus";
    Console.WriteLine(p);
}

Whereas here I output the value in the variable called name. Variables are basically a box with name on (name) which hold values (nexus)

I suggest you look at some basic programming tutorials before you tackle Unity

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
SE1986
  • 2,534
  • 1
  • 10
  • 29
  • Note that the code in the `Using` function will not compile because it's a `static` function while `Attack` is a non `static` function. You **can't** call non `static` function from a `static` function. – Programmer Aug 08 '18 at 22:03
  • And, that first sample of code (calling the instance method `Attack` from the static method `Using`) won't compile. The two `Start` method examples are a little weird too. As @itsme86 noted, the first one creates a new Player object, but, since the reference immediately goes out of scope, that object is lost forever and is eligible for "Garbage collection". The second example would only work if the Player class had a public string property named `name` (which, by convention, should really start with a capital letter). The WriteLine call relies on Player having a ToString method _override_ – Flydog57 Aug 08 '18 at 22:03
  • NB, Just quoting the OPs code for the purpose of explanation. Have left out comments re: code quality of and other factors which are outside of the scope of the question – SE1986 Aug 08 '18 at 22:17
1

On top of the other answers, you can also use this to disambiguate. Common example:

public MyType(this name) => this.name = name;

Or to use Extension Methods:

public static void MyCustomExtensionMethod(this Foo foo) { }
...
public class Bar() : Foo
{
   // I did not create Foo and do not have access to Foo
   this.MyCustomExtensionMethod();
}
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
1

You may want to just read some more OOP theory before diving into code. I can hopefully throw some pointers which should help you get on track :)

Firstly, from inside a class, calling Attack() is the same as this.Attack(). this is just a little more explicit that you're talking about the current object and not some other function called Attack.

Your Player class is your template for what a Player should like. You should not access Player. because this is accessing your template and not an object of a player. E.G

Player.Something() //Accesses a function inside the Player class.

You will rarely do something like the above, it's a more complicated idea. These are called static properties/functions and apply to the template of the class. All your functions here are static when they should not be :)

So your class is your template of what a player should be like, but how do we make an object of a player?

public class UsingStuff : MonoBehaviour 
{
    private void Start () {
        Player myPlayer = new Player(); //Makes an object called myPlayer
        Player otherPlayer = new Player(); //Another player object
        //For functions
        myPlayer.Attack(); //myPlayer will attack
        otherPlayer.Move(); //otherPlayer.move
        //For variables
        myPlayer.name = "Dave";
        otherPlayer.name = "Emma";
        //Now both our players have different names
    }
}

Hopefully this makes a bit more sense, Your class is your template of what a player should have/be able to do. To actually use/make players you create objects of them, and then each one has their variables. For example if Ouch(){this.hp--); then myPlayer.Ouch() would cause myPlayer to lose 1 of his health, but otherPlayer would not be affected.

Prodigle
  • 1,757
  • 12
  • 23
0

Alright, so first off thank you to everyone for pointing at different details. I think I am getting my head around things. I now have a working example:

public class Player : MonoBehaviour {

    public string name;
    public int power;
    public int speed;

    public void gameData() {
        print ("Player name = " + name);
        print ("Player power = " + power);
        print ("Player speed = " + speed);   
    }
    private void Attack () { }
}
...

public class UsingStuff : MonoBehaviour {

var P1 = new Player();
var P2 = new Player();
var P3 = new Player();

private void Start () {
    P1.name  = "Bill";
    P1.power = 10;
    P1.speed = 30;

    P2.name  = "Bob";
    P2.power = 100;
    P2.speed = 3;

    P3.name  = "Jerry";
    P3.power = 50;
    P3.speed = 10;

    P1.gameData();
    P2.gameData();
    P3.gameData();
}

However, even though the program works, I am getting a warning that is specific to using Unity and MonoDevelop, so that is a different issue all together. Thank you all for your help.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
shodai
  • 113
  • 2
  • 11
  • 3
    This site is not like forums. You should not post replies as answers. You can use comments, or open a new question. – Nikaas Aug 09 '18 at 06:45
  • 1
    Agreed, probably best to add and edit to the bottom of your original post because this will get missed as it is classed as an answer – SE1986 Aug 09 '18 at 09:48
0

I´m not able to comment so i will answer this way on your second post:

First case:

If you don`t need the player as a script connected with a GameObject and Unity functions like Update loops: Remove the inheritance (from MonoBehaviour) and it will work: public class Player { ... }

Second more common case:

If you need a Player as a object in the scene which uses Unity functions leave the Player Script as it is. The mistake is in using var P1 = new Player(); You know that have to add your Script to a GameObject in Unity Scene? Watch some basic Unity tutorials to understand: https://unity3d.com/de/learn/tutorials/topics/interface-essentials/game-objects-and-components?playlist=17090

This shows how to control a GameObject Script from another Script: https://unity3d.com/de/learn/tutorials/topics/scripting/activating-gameobjects?playlist=17117