繁体   English   中英

Unity C#类和对象

[英]Unity C# Class and Objects

不好意思,我很抱歉这将是一个相当愚蠢的问题,但是我试图全面了解对象的用途和用途。 具体来说,我在Unity中工作,但是我不确定这是否重要。 另外,我还应该提到这种语言是压倒性的。 但是,这是我正在研究的简单示例。

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();
    }
}

所以这是问题:

  1. 调用函数Attack()与this.Attack有什么区别? 从新手的角度来看,他们似乎做的完全一样。 但是,我假设我的示例过于简单。
  2. 我使用随机名称nexus创建了Player类的对象。 但是,当我从其他类调用函数时,我似乎使用的是类名而不是此变量名。 那么创建变量名的目的是什么?

我现在暂时将其保留在这两个位置上,希望这将有助于在其他方面产生一些混淆。 谢谢您的帮助。

调用函数Attack()与this.Attack有什么区别?

例如,当您对类Player进行编码时,如果要使用方法“ Attack()”,则可以通过键入Attack()或this.Attack()来实现。 在两种情况下它都做相同的事情。

当您使用“ this”时。 您保证使用的方法是在您所使用的类上实现的。 例如:

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

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

GroupAttack和GroupAttackWithThis方法之间没有区别。

查看差异的有用链接: 在Java中,this.method()和method()之间有什么区别?

我使用随机名称nexus创建了Player类的对象。 但是,当我从其他类调用函数时,我似乎使用的是类名而不是此变量名。 那么创建变量名的目的是什么?

发生这种情况是因为您将函数“ Move”设置为静态,这意味着对于该类的每个实例,它都将完全相同。 当您希望方法或变量对于类的每个实例每次都具有相同的值或具有相同的行为时,将使用静态。 如果您的方法不是静态的,则需要使用变量的名称来使用它,这是因为您希望您的方法为每个实例更改其行为。 一个简单的例子:

public string GetName(){
    return name;
}

此方法将为每个Player返回一个不同的名称(将在变量中返回播放器的名称)。 因此,如果您这样做:

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

变量“ jhonsName”将包含一个值为“ Jhon”的字符串。

我希望这对您有帮助,并为您的游戏带来好运。

当您执行Player nexus = new Player(); ,您正在创建类型(/类)“播放器”的新实例(/对象)。 变量nexus是对象引用(即,它引用您刚创建的对象实例)。 一旦有了实例,就可以在该对象上调用实例方法,设置或读取其属性(顺便说一下,这些属性都不存在)。 由于仅对该对象有一个引用( nexus变量),所以当该引用超出范围时(在函数末尾),该对象将不再被任何对象引用,并且可以进行垃圾回收。

当使用static关键字声明方法(/函数)时,是在类级别而不是实例级别创建它。 如果要调用非静态的UpdateAttack方法,则必须说nexus.Updatenexus.Attack 要调用静态的UsingMove方法,可以使用这样的类名(Player): Player.UsingPlayer.Move

您发布的代码无法编译,是吗? 您不能从静态方法调用实例方法。 您不能从静态方法Using调用实例方法Attackthis.Attack (那里没有“ this”( this是与实例方法关联的当前对象实例))。 最好张贴至少可以编译的代码(除非您在注释中说),否则//this is the code that doesn't compile

您还只能在Start方法中创建一个新的Player实例,这有点奇怪。 通常,您可以在其他类或静态工厂方法中创建对象的实例(并非总是如此,但通常如此)。

阅读有关面向对象编程的性质,C#的static关键字和对象实例的性质(通常)的信息。 您可能还想阅读C#的属性。

哦,从长远来看,命名Using会很痛苦(小写的using是已经有两种含义的C#关键字)。

最后,回答您的问题,“以这种方式调用实例方法: Attack()或以这种方式: this.Attack()具有相同的语义。” 当然,如上所述,如果尝试从静态方法调用实例方法,则不能使用任何一种形式。

Unitys MonoBehaviour与普通C#类之间存在一些差异。 我建议观看一些Unity教程。 Unity脚本是面向场景的。

  1. 没有区别。 can be used to mark something as "from the class object" (Normally Properties or Variables) to distinguish from parameters. 可以用来将某些东西标记为“来自类对象”(通常是Properties或Variables)以区别于参数。

  2. 编写 应该是一个警告,因为您不应该对MonoBehaviour这样做。

通过将脚本“ Player”放在GameObject上,可以在场景中创建一个Player。 您应该从GameObject访问Player脚本。 因此,您应该删除方法上的“静态”。 然后放 在UsingStuff内部(在公共类UsingStuff下:MonoBehaviour {)。 然后将Player拖动到Player的占位符上。 您将在场景中使用UsingStuff-Script在GameObject上找到它。 现在,您可以在开始方法中调用player.Move()(带有小p)。

. 尝试为您的变量再命名。 它已经存在于每个MonoBehaviour中。 它指的是脚本所在的GameObject的名称。 您的命名也应该发出警告。

  1. this关键字的意思是“对类的当前实例的引用”确实是语法糖(它可以使您的代码更清晰易读)

当你做

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

在幕后,编译器将按以下方式执行它:

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

所以在您的上下文中,它们是相同的。

有时很有用,请参阅这篇文章

  1. 如果我理解正确,那么这个问题与为什么您需要一个名为name的变量,而不仅仅是将对象命名为玩家名称有关。 变量“名称”和对象名称是两件事

假设您想将玩家名称输出到屏幕

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

}

在上面的方法中,我无法[简单地]做

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

而在这里,我在名为name的变量中输出值。 变量基本上是一个名称为(name)且具有值(nexus)的框

我建议您在学习Unity之前先看一些基本的编程教程。

除了其他答案,您还可以使用this来消除歧义。 常见示例:

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

或使用扩展方法:

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();
}

在深入研究代码之前,您可能只想读一些OOP理论。 我希望可以抛出一些指针,这将有助于您步入正轨:)

首先,从类内部调用Attack()与this.Attack()相同。 这只是在更明确地表明您正在谈论当前对象,而不是其他一些称为Attack的函数。

Player类是您需要的模板。 您不应该访问Player。 因为这是在访问您的模板而不是播放器的对象。 例如

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

您很少会做类似上面的事情,这是一个更复杂的想法。 这些称为静态属性/功能,并应用于类的模板。 您的所有函数在不应该静态的时候都是静态的:)

因此,您的课程是您的球员模样的模板,但是我们如何制作球员的对象呢?

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
    }
}

希望这更有意义,您的课程是您球员应该/能够做的事情的模板。 要实际使用/制作播放器,您需要创建它们的对象,然后每个对象都有其变量。 例如,如果Ouch(){this.hp--); 那么myPlayer.Ouch()会导致myPlayer失去1的生命值,但otherPlayer不会受到影响。

好的,首先,谢谢大家指出不同的细节。 我想我正在全神贯注。 我现在有一个工作示例:

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();
}

但是,即使该程序可以运行,但我仍收到有关使用Unity和MonoDevelop的警告,因此这是一个完全不同的问题。 谢谢大家的帮助。

我无法发表评论,因此我将在您的第二篇文章中回答:

第一种情况:

: Remove the inheritance (from MonoBehaviour) and it will work: public class Player { ... } 如果你不`吨 :删除继承(从MonoBehaviour),它会工作: public class Player { ... }

第二种较常见的情况:

如果在使用Unity函数的场景中需要播放器作为对象,则保持播放器脚本不变。 错误在于使用 您知道必须将脚本添加到Unity Scene中的GameObject吗? 观看一些基本的Unity教程以了解: https : //unity3d.com/de/learn/tutorials/topics/interface-essentials/game-objects-and-components?playlist=17090

这显示了如何从另一个脚本控制GameObject脚本: https ://unity3d.com/de/learn/tutorials/topics/scripting/activating-gameobjects?playlist=17117

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM