unity 2D 与NPC对话

unity 2D 与NPC对话,第1张

【基础】

将鼠标移动到NPC身上,这时候鼠标的箭头会根据NPC的种类产生变化,例如对话时是。使用鼠标左键单击NPC,目标就会转换成NPC。选中目标NPC后,再次单击鼠标左键,角色就会自动移动到NPC旁边并与NPC进行对话了。当然,整个过程您可以直接使用双击鼠标左键完成,一步到位。

【进阶】

有时候您会发现NPC的周围挤满了围观的人群,没有办法靠近NPC和他对话,有两个方法可以帮助您解决这个问题。

1、 在场景内隐藏其他的玩家

使用默认快捷“F9”,隐藏场景内的其他玩家,就可以靠近NPC和他对话了。如果想恢复显示,则再按一次“F9”。

2、 直接穿越其他的玩家

移动鼠标到NPC的方向,按住“SHIFT”键,当鼠标的箭头发生变化成为后,双击鼠标左键您就可以直接穿越其他玩家的身体靠近NPC和他对话了。

【小提示】

不是所有的NPC都会和您对话。

有时其他玩家和NPC重合在了一起,让您很难点到NPC,按一下“F9”键把他隐藏掉就可以了。

额.....你把人物间对话事件的脚本放到合适的触发判定条件下就可以了呀......具体的就要看需求而定了。有的时候是加载完场景就播放,有的时候是 *** 作人物触碰触发器播放等等,更具体的你可以到paws3d去看

在上一篇关于 P/INVOKE 的文章中,我们学习了如何从 Unity 内部调用非托管方法,以及如何跨互 *** 作屏障传递参数和返回值。

现在让我们开始DllImport在我们的代码库中到处撒播以获得乐趣和利润!对?好…

那么让我们来看看我们是如何在 Baracoda 的项目中应对这些挑战的!

假设您有一个针对静态库编译的 iOS 代码的现有版本,libios_plugin.a. 因此,让我们添加插件的 Android 版本libandroid_plugin.aar,其中包含内部libandroid_plugin.so.

然后在尝试执行本机代码时观察它失败:

我们的第一个问题是,在 iOS 上,我们使用的是静态链接库,它要求传递给的名称DllImport是__Internal.

但是,我们有一个名为 的 Android 版本的动态链接库libandroid_plugin.so,并且该名称需要在DllImport.

我们可以使用///指令和Unity的平台脚本符号来使用条件编译#if,如#elif或选择#else将基于当前平台编译的属性的版本。#endifUNITY_ANDROIDUNITY_IOS

万岁,它有效!但是,呃……如果我们需要更多方法,那就太冗长了,而且我们现在只支持 2 个平台。那么我们能做些什么来避免重复这个巨大的块呢?

好吧,库名称必须是一个常量字符串,所以const string也可以。让我们重构:

我们编写的内容适用于单个类,但随着 API 表面变大,我们可能希望将这些本地方法分组为对象——根据 单一 责任 原则—— 每个对象代表我们想要的不同服务访问。

但是因为这个LIBNAME变量现在是私有的,所以我们必须在每个类中复制/粘贴指令,这与 D on't R epeat Y ourself原则相矛盾。所以让我们创建另一个类来为我们保存它!

导入现在看起来像这样:

不太冗长,易于阅读,易于扩展。现在我们肯定完成了,对吧?

那么,你能为最终调用那些非托管方法的特性编写单元测试吗?

因此,也许您可 以针对实际实现编写测试,因为本机库只是提供一些业务逻辑,但也许您首先拥有它的原因是因为它使您可以访问外部资源?也许没有可用的桌面版本的库,测试甚至无法在编辑器中运行?

无论如何,这个非托管代码应该被考虑在被测单元 之外,但是您仍然需要访问它在真实代码中提供的服务。

在这种情况下,最好的解决方案通常是将服务的实现与其接口分离。

现在我们可以为测试实例化一个假的,但仍然将真实的实现用于生产!

这仍然是一个玩具示例,但是因为我们没有创建非托管对象的实例,而只是在讨论似乎是自由函数或静态方法的东西。

有时只有一个服务实例可以与之对话是有意义的,有时则不然,您需要能够动态地创建新实例。那么,我们如何从 C# 中与它们交互呢?

在 C 或 C++ 中动态创建对象时,程序将分配一些内存,在其中构造对象,并返回指向它的 指针 。

等等,别跑!没关系!

在编组指向 C# 的非托管指针时,运行时可以将其转换为IntPtr. 您可以将其视为非托管对象的不透明句柄,除了将其交还给非托管端外,您不能直接使用它做很多事情。

所以现在创建 C# 类的新实例也会创建非托管对象的新实例,然后我们可以对其进行方法调用。甜的!

我们只是忘记了一个细节:我们创建了一个 非托管 对象,这意味着 GC 不知道如何回收它,甚至默认 都不尝试!

因此,当 C# 类被垃圾回收时,让我们停止 泄漏该非托管对象。

在 C# 中,类发出需要清理步骤的信号的首选方式是实现IDisposable接口。

假设有一个函数用于销毁我们的非托管对象,它的 API 如下所示:

现在实现Dispose()非常简单:

随着这一变化,我们现在可以很好地管理我们的资源并执行必要的清理工作。

然而,既然我们已经引入了手动资源管理,我们就会冒着尝试引用已被释放的非托管对象的风险,所以让我们让它更安全!

幸运的是,C# 标准库正是我们所需要的:SafeHandle!它本来是用来保持 Win32 句柄的,但它的 API 和终结保证使它非常适合我们的目的。

从 继承时SafeHandle,需要做 3 件事。

因此,这就是SafeHandle我们示例中自定义的样子:

现在我们只需要在任何地方都替换IntPtr为 with CameraServiceHandle,除了在销毁方法中仍然需要一个IntPtr.

我们的 C# 端服务现在在内部使用句柄:

我们已经做到了!

我们现在已经从到处添加临时[DllImport] static extern方法(冗长、难以测试且不一定资源安全)转变为专门设计的方法。

我们有一些小包装;它们封装良好,不会阻止对依赖它们的代码进行测试,易于添加跨平台支持,并且我们现在有系统的方法来保证与非托管对象交互时的资源和类型安全!

这就是我们在 Baracoda 如何使用 P/Invoke 的导览!

利用 P/Invoke 使我们能够编写跨平台库并与之交互,从而将我们研发团队在机器学习和计算机视觉方面的内部知识带到我们的 Unity 游戏 中!

我们计划发布更多 Unity 开发者内容,敬请期待!


欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/bake/11809475.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-18
下一篇2023-05-18

发表评论

登录后才能评论

评论列表(0条)

    保存