对,我很抱歉这是一个相当愚蠢的问题,但是我试图全面了解对象的用途和用途。具体来说,我在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();
}
}
所以这是问题:
我现在暂时将其保留在这两个位置,希望这会有助于对其他一些事情产生一些困惑。 谢谢您的帮助。
答案 0 :(得分:3)
调用函数Attack()与this.Attack有什么区别?
例如,在编写类Player时,如果要使用方法“ Attack()”,则可以通过键入Attack()或this.Attack()来实现。在两种情况下它都做同样的事情。
使用“ this”时。您保证使用的方法是在您所使用的类上实现的。例如:
Add()
GroupAttack和GroupAttackWithThis方法之间没有区别。
有用的链接来查看不同之处: In Java, what is the difference between this.method() and method()?
我创建了具有随机名称nexus的Player类的对象。但是,当我从其他类调用函数时,我似乎使用的是类名而不是此变量名。那么创建变量名的目的是什么?
发生这种情况是因为您将函数“ Move”设置为静态,这意味着对于该类的每个实例,它将执行完全相同的操作。当您希望方法或变量对于类的每个实例每次都具有相同的值或具有相同的行为时,将使用静态。 如果您的方法不是静态的,则需要使用变量的名称来使用它,这是因为您希望您的方法为每个实例更改其行为。 一个简单的例子:
public void GroupAttack(DifferentPlayer ally){
Attack();
ally.Attack();
}
public void GroupAttackWithThis(DifferentPlayer ally){
this.Attack();
ally.Attack();
}
此方法将为每个播放器返回一个不同的名称(将在变量中返回播放器的名称)。因此,如果您这样做:
public string GetName(){
return name;
}
变量“ jhonsName”将包含一个值为“ Jhon”的字符串。
我希望这对您有用,并祝您游戏顺利。
答案 1 :(得分:2)
执行Player nexus = new Player();
时,您正在创建类型(/类)“播放器”的新实例(/对象)。变量nexus
是对象引用(即,它引用您刚创建的对象实例)。一旦有了实例,就可以在该对象上调用实例方法,设置或读取其属性(顺便说一下,这些属性都不存在)。由于仅对该对象有一个引用(nexus
变量),所以当该引用超出范围(在函数末尾)时,该对象将不再被任何对象引用,并且可以进行垃圾回收。
使用static
关键字声明方法(/函数)时,您是在类级别而不是实例级别创建它。如果要调用非静态Update
或Attack
方法,则必须说nexus.Update
或nexus.Attack
。要调用静态的Using
或Move
方法,您可以使用以下类名(Player):Player.Using
或Player.Move
。
您发布的代码无法编译,对吗?您不能从静态方法调用实例方法。您无法从静态方法Attack
调用实例方法this.Attack
或Using
(那里没有“ this”(this
是与实例关联的当前对象实例)方法))。最好发布至少可以编译的代码(除非您在评论中说//this is the code that doesn't compile
您还只能在Start
方法中创建一个新的Player实例,这有点奇怪。通常,您可以在其他类或静态 factory 方法中创建对象的实例(并非总是如此,但通常如此)。
通读有关面向对象编程的性质,C#的static
关键字和对象实例的性质(通常)的信息。您可能还想阅读C#的属性。
哦,从长远来看,命名Using
会很痛苦(小写的using
是已经有两种含义的C#关键字)。
最后,要回答您的问题,“以这种方式调用实例方法:Attack()
或以这种方式:this.Attack()
具有相同的语义。”当然,如上所述,如果尝试从静态方法调用实例方法,则不能使用任何一种形式。
答案 2 :(得分:2)
Unitys MonoBehaviour与常规C#类之间存在一些差异。我建议观看一些Unity教程。 Unity脚本是面向场景的。
没有区别。 this.Something 可用于将某些东西标记为“来自类对象”(通常是“属性”或“变量”),以区别于参数。
编写 Player nexus = new Player(); 应该是一个警告,因为您不应该对MonoBehaviour这样做。
您可以通过将脚本“ Player”放在GameObject上在场景中创建一个Player。您应该从GameObject访问Player脚本。因此,您应该删除方法上的“静态”。然后将 public Player player; 放在UsingStuff(在公共类UsingStuff:MonoBehaviour {下)中。然后将Player拖动到Player的占位符上。您将在场景中使用UsingStuff-Script在GameObject上找到它。现在,您可以在开始方法中调用player.Move()(带有小p)。
尝试为变量 name 命名。它已经存在于每个MonoBehaviour中。它指的是脚本所在的GameObject的名称。您的命名也应该发出警告。
答案 3 :(得分:1)
this
关键字的意思是“对类的当前实例的引用”实际上是语法糖(可以使您的代码更清晰地阅读)这样做的时候
public static void Using() {
Attack();
this.Attack();
}
在后台,编译器将按以下方式执行它:
public static void Using() {
this.Attack();
this.Attack();
}
所以在您的上下文中,它们是相同的。
有时候有用,请参见this post
让我们说您要在屏幕上输出玩家姓名
void Start () {
Player nexus = new Player();
}
在上述方法中,我无法[简单]做到
void Start () {
Player p = new Player();
p.name = "nexus";
Console.WriteLine(p);
}
在这里,我在名为name的变量中输出值。变量基本上是一个在(name)上具有名称的框,其中包含值(nexus)
我建议您先了解一些basic programming tutorials,然后再解决Unity
答案 4 :(得分:1)
除了其他答案之外,您还可以使用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();
}
答案 5 :(得分:1)
在深入研究代码之前,您可能只想阅读更多OOP理论。我希望可以抛出一些指针,这将有助于您步入正轨:)
首先,在类内部,调用Attack()与this.Attack()相同。这只是您在谈论当前对象,而不是其他一些称为“攻击”的功能。
您的Player类是您需要Player的模板。您不应该访问Player。因为这是在访问您的模板而不是播放器的对象。 E.G
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不会受到影响。
答案 6 :(得分:0)
好的,所以首先感谢大家指出不同的细节。我想我正在全神贯注。我现在有一个可行的示例:
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的警告,因此这是一个完全不同的问题。谢谢大家的帮助。
答案 7 :(得分:0)
我无法发表评论,因此我将在您的第二篇文章中回答:
第一种情况:
如果不要 需要玩家将其作为与GameObject和诸如Update循环之类的Unity功能连接的脚本:删除继承(来自MonoBehaviour),它将起作用:
public class Player
{
...
}
第二种常见情况:
如果需要使用Unity功能的场景中的Player作为对象,请保持Player脚本不变。错误在于使用 var P1 = new Player(); 您知道必须将脚本添加到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