【问题标题】:How do I access script B,C,D singularly in script A?如何在脚本 A 中单独访问脚本 B、C、D?
【发布时间】:2017-01-06 07:20:52
【问题描述】:

我的对话系统遇到了问题。

我有一个脚本“对话管理器”,它接受一个“对话持有者”脚本,用于与用户进行输入/输出。当玩家靠近 npc 并按空格键时,每个 npc 都会有自己的对话持有者传递给对话管理器。

在 dialogManager 中,我像这样引用对话持有者脚本:

public dialogueHolder dh;

在 dialogHolder 脚本中,我有这段代码将 dialogHolder 初始化到 dialogManager 中:

dManager.dialogueHolder = this;

这在使用基本 dialogHolder 脚本时可以正常工作,但它只是单个 NPC 对话的模板。我怎样才能使多个对话持有者可以在 dialogManager 中以相同的方式引用?例如,我有一个脚本dialogueHolder_yellowMage,其中包含与法师npc有关的某些对话,我如何将其引用到DialogueManager中的dh变量中?因为 dialogHolder_yellowMage 与 dialogHolder 的标题不同,所以我不能这样引用它。


我试图改变

public dialogueHolder dh; 

public Object dh;

但是我无法引用 dialogHolder 脚本中的任何变量。

抱歉,我是 stackOverflow 和 C# 的新手。请帮助新手!

【问题讨论】:

  • 阅读继承。如果您从 dialogHolder 派生 dialogHolder_yelllowMage 它应该“适合”到变量(类型为 dialogHolder)。另一种选择是使用接口。 msdn.microsoft.com/en-us/library/ms173149.aspx
  • 我不太了解您的架构,但无论如何。如果您让您的 dialogHolder_yellowMage 脚本继承 dialogHolder 那么您将能够在管理器中引用它。
  • 太棒了!我非常感谢您的快速回复。谢谢!!!!!!
  • @GPlourde 似乎您没有正确使用 C# 对象 - 听起来您正在为每个 npc 定义一个独特的脚本?我已经开发了一些 Unity 对话系统,所以我确信这没有必要。
  • @Luke 如何在单个脚本上为每个 npc 单独对话?看来我必须给每个 npc 一个单独的对话持有者实例,因为它们都有彼此不同的字符串。有没有更好的办法?我想改进我糟糕的编码习惯哈哈。

标签: c# unity3d


【解决方案1】:

类与实例

看起来你正在做这种事情:

public class dialogueHolder_yellowMage {

    public string MessageToSay;

}

public class dialogueHolder_redMage {

    public string MessageToSay;

}

public class dialogueHolder_blueMan {

    public string MessageToSay;

}

..

// public dialogueHolder_? dh;
public object dh; // Only this would work, but it's not what you want!

首先要注意的是它们都在重复同样的事情(或者至少是在重复同样的概念)。与其为每个 NPC 设置一个唯一的类,不如使用一个代表对话的类:

public class DialogueHolder {

    // The message they'll say
    public string MessageToSay;

}

...

// Then we *instance* one for each of our NPCs:
DialogueHolder yellowMage = new DialogueHolder();
yellowMage.MessageToSay = "I'm feeling great!";

DialogueHolder redMage = new DialogueHolder();
redMage.MessageToSay = "I'm so angry!";
..

在这种情况下,它们都使用同一个实例。这意味着您现在可以执行public DialogueHolder dh; 并且可以正常工作。

继承

如果一个类描述了一个概念,那么继承就是描述相关的概念。例如,狗是动物的一种。法师是NPC的一种。但是对话通常没有这些独特的类别,所以继承可能不是您想要使用的。

统一组件

当您使用 Unity 时,我们可以将这些实例变成漂亮且可视的东西 - 在检查器中使用 组件。组件脚本如下所示:

// DialogueHolder.cs
using UnityEngine;
using System.Collections;    

public class DialogueHolder : MonoBehaviour { // (This is also inheritance)

    // The message they'll say
    public string MessageToSay;

}

常见误解的时间到了: Unity 默认创建组件脚本。这常常使人们认为所有类都必须继承 MonoBehaviour,这不是 Unity 的工作方式。仅当某些东西作为组件确实有用时才继承 MonoBehaviour。

在编辑器中单击您的一个 NPC,然后查看检查器;你会看到一个“添加组件”按钮。单击它,然后您将获得脚本选项:

在那里,您将能够选择您的DialogueHolder 课程。一旦你添加了它,你会在检查器中看到这样的东西:

Unity 已为您实例化该类作为 NPC 游戏对象的组件

这非常有用;然后您可以单独编辑Message To Say。您班级中的大多数 public 字段将在检查器中可见(并可编辑),因此您可以添加一堆其他对话相关字段:

// DialogueHolder.cs
using UnityEngine;
using System.Collections;    

public class DialogueHolder : MonoBehaviour {

    // The message they'll say
    public string MessageToSay;

    // Some kind of 2D chat head image
    public Texture2D ChatHead;

    // etc!

}

从游戏对象中获取 DialogueHolder

假设你的玩家正在场景中走动并且在某个游戏对象的聊天范围内。您可以使用tagging 快速检查游戏对象x 是否为NPC。在您的场景启动时,通过finding all GameObjects that are tagged as an NPC 存储所有可用 NPC 的列表,然后循环检查玩家与每个 NPC 的距离。当玩家在其中一个范围内时,您可以像这样抓住 DialogueHolder:

// Try getting the dialogue holder:
DialogueHolder dh = aGameObject.GetComponent<DialogueHolder>();

if (dh == null) {

    // This NPC doesn't feel like talking (you didn't give it a DialogueHolder)

} else {

    // Do something with dh

}

功能齐全的对话系统当然超出了这里的范围,但无论如何这都是基础!

【讨论】:

  • @abatishchev 代码不需要重新格式化 - 它的样式是 Unity3D 的常用样式。
  • @abatishchev 即查看Unity API examples 中的一些linked in this answer。最好避免将您的首选样式强加给其他用户。
  • 我刚刚在 C# 的 common 中制作了它(参见 MSDN guidance)。这总是取决于你。附言那种风​​格很烂我的拙见。
  • @abatishchev 这是一个 Unity 问题,Unity 有自己的约定; FWIW 我喜欢这两种风格(出于必要),但仅仅因为 不喜欢 Unity 约定并不意味着你应该将答案更改为其他内容:)
  • 我不知道那是 Unity 风格。所以只是格式化以遵循常见的 C# 样式。真的不是要强制执行任何事情。
猜你喜欢
  • 2017-06-16
  • 2018-07-15
  • 2016-07-30
  • 1970-01-01
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-19
相关资源
最近更新 更多