简体   繁体   English

什么更好:链接到游戏对象或 Unity 中的类?

[英]What is better: link to a GameObject or to a Class in Unity?

Example: GameObject A has a script attached to it called MakeItRain.示例:游戏对象 A 附加了一个名为 MakeItRain 的脚本。 Inside that script is a public void Drizzle();在那个脚本里面是一个 public void Drizzle();

GameObject B also has a script and wants to tell MakeItRain to do Drizzle(); GameObject B 也有一个脚本,想告诉 MakeItRain 做 Drizzle();

Inside the script of GameObject B, I can do this:在 GameObject B 的脚本中,我可以这样做:

public GameObject makeitrain;

and then I have to use GetComponent to reach Drizzle();然后我必须使用 GetComponent 来达到 Drizzle(); in my code.在我的代码中。 In the inspector, I drop GameObject A into the slot of makeitrain and I'm done.在检查器中,我将 GameObject A 放入 makeitrain 的插槽中,然后就完成了。

However, I could also do this in the script of GameObject B:但是,我可以在 GameObject B 的脚本中执行此操作:

public MakeItRain makeitrain;

and then just call makeitrain.Drizzle();然后只需调用makeitrain.Drizzle(); in my code of GameObject B's script, without GetComponent.在我的 GameObject B 脚本代码中,没有 GetComponent。

In both cases, in the Inspector, I have to drag and drop GameObject A into the slot of GameObject B.在这两种情况下,在检查器中,我必须将游戏对象 A 拖放到游戏对象 B 的插槽中。

Is there a difference or reason why I should definitely not do the last option?我绝对不应该做最后一个选项有什么不同或原因吗? I understand that the first method gives me more flexibility because I could call other components of GameObject A as well and not just the script's stuff.我知道第一种方法给了我更大的灵活性,因为我也可以调用 GameObject A 的其他组件,而不仅仅是脚本的东西。 Just wondering if there is any other rationale for not doing the second method.只是想知道不使用第二种方法是否还有其他理由。

The answer depends if you need to call any function or use variable from the MakeItRain script.答案取决于您是否需要调用任何函数或使用MakeItRain脚本中的变量。

If you don't need to to call any function in the MakeItRain script or access any variables from it then it is better to use GameObject as the reference.如果您不需要在MakeItRain脚本中调用任何函数或MakeItRain访问任何变量,那么最好使用 GameObject 作为参考。 Also, if what you need to do is activate, de-active, rotate the GameObject then use the GameObject as reference.此外,如果您需要做的是激活、停用、旋转游戏对象,然后使用游戏对象作为参考。

On the other hand, if you need to be able to call a function such as Drizzle or access a variable from the MakeItRain script from multiple places , then you need to use the MakeItRain reference.另一方面,如果您需要能够从多个地方调用Drizzle等函数或访问来自MakeItRain脚本的变量,则需要使用MakeItRain引用。 At this time, it doesn't make sense to use the GameObject reference since by using it, it's required to use GetComponent every-time you need to call a function or access a variable from the MakeItRain script attached to it.此时,使用GetComponent引用是没有意义的,因为通过使用它,每次需要调用函数或访问附加到它的MakeItRain脚本中的变量时,都需要使用GetComponent

Finally, when using the MakeItRain script to reference your object, you can directly and easily access the GameObject it is attached to without using the makeitrain.gameObject .最后,当使用MakeItRain脚本引用您的对象时,您可以直接轻松地访问它所附加的makeitrain.gameObject ,而无需使用makeitrain.gameObject This doesn't require the use of the GetComponent function.这不需要使用GetComponent函数。

Just wondering if there is any other rationale for not doing the second method.只是想知道不使用第二种方法是否还有其他理由。

Performance issue due to the required use of the GetComponent function is the reason.由于需要使用GetComponent函数而导致的性能问题是原因。 Using it once in the Start or Awake function and initializing your MakeItRain variable is better.StartAwake函数中使用一次并初始化MakeItRain变量会更好。

For example, this is better:例如,这更好:

public MakeItRain makeitrain;

void Start()
{
    makeitrain = GetComponent<MakeItRain>();
}

void Update()
{
    makeitrain.Drizzle();
}

than this:比这个:

public GameObject makeitrain;

void Update()
{
    makeitrain.GetComponent<MakeItRain>().Drizzle();
}

And should be used to avoid having to search for the component on the native side every frame .并且应该用于避免每帧都必须在本机端搜索组件。

Using MakeItRain and explicitly defining the type is better than using GameObject .使用MakeItRain并明确定义类型比使用更好的GameObject

As @hacksalot commented, using MakeItRain offers strong typing .正如@hacksalot 评论的那样,使用MakeItRain提供了强类型 One of the benefits of this is related to your comment:这样做的好处之一与您的评论有关:

In both cases, in the Inspector, I have to drag and drop GameObject A into the slot of GameObject B.在这两种情况下,在检查器中,我必须将游戏对象 A 拖放到游戏对象 B 的插槽中。

If you explicitly set the public variable type to MakeItRain rather than GameObject , it is not possible to drag and drop a GameObject A into the slot of GameObject B unless GameObject A is has a script of the correct type.如果你明确地设置公共变量类型MakeItRain而不是GameObject ,这是不可能的拖放游戏物体进入一个游戏对象B的插槽,除非游戏对象A是具有正确类型的脚本。 This gives you a compile-time/editor-time check that you are linking to the correct GameObject in the Unity Editor inspector .这为您提供了一个编译时/编辑器时检查,以确保您在 Unity 编辑器检查器中链接到正确的游戏对象

Also, while not necessarily so, using GameObject references often encourages messier code , whether because of unnecessary chaining of methods together (eg GetComponent ) just because the type wasn't specified, or because it adds a bit of friction to writing & using helper methods.此外,虽然不一定如此,但使用GameObject引用通常会鼓励更混乱的代码,无论是因为没有指定类型而将方法不必要地链接在一起(例如GetComponent ),还是因为它增加了编写和使用辅助方法的一些摩擦. Consider even in a simple example which one reads better:甚至在一个简单的例子中考虑哪个更好读:

makeitrain.Drizzle()

makeitrain.GetComponent<MakeItRain>().Drizzle()


I understand that the first method gives me more flexibility because I could call other components of GameObject A as well and not just the script's stuff.我知道第一种方法给了我更大的灵活性,因为我也可以调用 GameObject A 的其他组件,而不仅仅是脚本的东西。

Note that you still have the flexibility to access GameObject , it's just a bit more verbose (which is one downside of this approach):请注意,您仍然可以灵活地访问GameObject ,只是有点冗长(这是这种方法的一个缺点):

public MakeItRain makeitrain;

void Start()
{
    makeitrain.gameObject.SetActive(false)
}

However, you'll likely be using helper methods anyway (for anything more than basic calls), or even wrapper methods (which are inconvenient to write but sometimes helpful for readability).但是,无论如何,您都可能会使用辅助方法(用于基本调用以外的任何内容),甚至是包装方法(编写起来不方便,但有时有助于提高可读性)。

In most cases, the benefits of linking to the class rather than the GameObject outweigh the downsides.在大多数情况下,链接到类而不是GameObject的好处大于坏处。

If u don't want to use GetComponent() , you can simply use SendMeassage() , like this如果你不想使用GetComponent() ,你可以简单地使用SendMeassage() ,就像这样

public Gameobject makeItRain;
void Start(){
    makeitrain.SendMeassage("Drizzle");
}

Another way to link a script is that use FindObjectOfType() , which do not need to drag and drop GameObject into the slot, here is the sample链接脚本的另一种方法是使用FindObjectOfType()它不需要拖放GameObject插入插槽,这里是样本

void Start(){
    MakeItRain makeitrain = FindObjectOfType("MakeItRain");
}

Also you can use Gameobject.Find() to link a GameObject instead of dragging into slot, but I don't recommand this way, it cost a lot performance since you need to find every single GameObject in scene.你也可以使用Gameobject.Find()来链接一个GameObject而不是拖到插槽中,但我不推荐这种方式,因为你需要找到场景中的每个游戏对象,所以它会消耗很多性能。

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

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