找回密码
 立即注册
查看: 983|回复: 0

Virt a mate(Vam)插件编写指南2

[复制链接]
发表于 2021-12-17 06:45 | 显示全部楼层 |阅读模式
前言:本篇承接上一篇。
文中插件脚本的完整版见仓库:

  • 触发器(Trigger)编写
如果你对Vam常规使用有一定了解的话,肯定会知道它里面有一种叫触发器(Trigger)的组件。它类似于Unity中的Action。当一个事件触发时,能通过这个触发器执行一系列的动作。就比如原子物体的碰撞触发器,我们可以对碰撞触发器添加比如播放音频,开关灯光等等操作。这样当原子物体在场景中受到碰撞时,就会执行播放对应音频和开关灯操作。这样就大大提高了我们操作的灵活性。
除了Vam原生自带的各种触发器,我们也是可以添加自己的触发器的。不过创建过程稍微有点麻烦,看官方的几个触发器的代码也有点复杂。但是我们可以通过将代码简单的封装下便可以大大方便我们的使用。完整代码参看文章开头链接。
封装后创建代码如下:
//加载触发器UI资源
SimpleTriggerHandler.LoadAssets();
//成就事件触发器
achieventTrigger = new EventTrigger(this, "成就触发事件");
Utils.SetupButton(this, "设置成就触发", achieventTrigger.OpenPanel, false);



自定义的触发器和自带的触发器原理是一样的

可以看到和自带的触发器使用完全一样了。

  • 事件注册
有了触发器,就需要有接受事件触发的目标。一个原子物体上Vam针对物体的各种属性已经给我们注册很多的属性(如scale,volume等)。比如可以通过音量变化触发器来驱动目标物体的缩放。



系统给我们提供了很多供触发的属性。

不过自带的目标属性往往无法完全满足我们的需求。这就需要我们注册自定义的属性。经过封装简化的方法如下:
Utils:
public static JSONStorableAction SetupAction(MVRScript script, string name, JSONStorableAction.ActionCallback callback)
{
    JSONStorableAction action = new JSONStorableAction(name, callback);
    script.RegisterAction(action);
    return action;
}               
MVRScript:
//注册一个我们自定义的触发目标。这样在触发器里就能选它了。当触发执行时,回调方法会被调用
Utils.SetupAction(this, "自定义的触发目标", () =>
{
    //在这里可以执行我们想要的操作。
    SuperController.singleton.Message("触发了自定义的目标");
});



代码运行后就能找到我们代码里注册的触发目标了



成功触发了结果


  • 简单调试工具编写
前面虽然讲了这么多,但是有一个让人头疼的问题一直没有解决——游戏的物体层级与结构。由于我们手头上不会有游戏的工程文件,所以我们对游戏场景的层次结构就没有直观的理解,只能靠猜。这样我们在写自己的逻辑时如果涉及到场景的层次结构就会一头雾水。为了更明确的搞清楚场景和物体的层次结构,我们需要写一个调试工具来辅助我们开发,提高效率。
//Utils
//......
//递归执行相关逻辑
Component[] comps = t.GetComponents<Component>();
if (comps.Length > 0)
{
    b.Append(' ', indent * 4 + 2).Append("\n");
    for (int i = 0; i < comps.Length; ++i)
    {
        Component c = comps;
        //生成树状结构
        b.Append(' ', indent * 4 + 4).Append("--").Append(c.GetType().FullName).Append("\n");
    }
}
//......

Utils.SetupButton(this, "打印当前所选物体的层次结构(简要)", () =>
{
    var atom = SuperController.singleton.GetSelectedAtom();
    if (atom == null) return;
    SuperController.singleton.ClearMessages();
    Utils.LogTransform(string.Format("{0}原子的结构", atom.name), atom.transform);
}, false);


如上,原理其实很简单。就是递归查找指定物体的所有子物体以及脚本。并将结构信息输出成树状文本结构进行输出。但当物体结构过于复杂时,在log信息窗口会出现截断。所以推荐是在游戏的日志文件output_log.txt进行查看。这个日志文件一般在C:\Users\xxx\AppData\LocalLow\MeshedVR\VaM下。



打印出的层级日志

通过上面这些元素的加入。我们就可以在Vam中写一些有趣的扩展了。比如我们可以考虑在里边加个五子棋小游戏。控制小姐姐和我控制人物下棋(利用Vam里傀儡模式),不过感觉在小姐姐动画控制方面还是有点麻烦。亦或是在里边加一个颠球的小游戏,达到一定目标小姐姐会做出一定的反应了(这个在开头的链接的脚本里有实现,不过还不太完善)。主要看自己开脑洞了。     
下面是一个简单的乒乓球游戏demo演示,目标很简单:尽可能让球在拍子上待久一点。达到一定时间会触发事件:
//这里使用枚举时,插件加载会导致游戏崩溃,所以这里没有使用枚举,直接使用了整数来判断状态
//段位判定
var stayDur = PingpongGameManager.singleton.ballStayDuration.val;
if (PingpongGameManager.singleton.gameChieventState == 0 && stayDur > 5)
{
    PingpongGameManager.singleton.gameChieventState = 1;
    achieventTrigger.Trigger();
    SuperController.LogMessage("不错哦!");
}
else if (PingpongGameManager.singleton.gameChieventState == 1 && stayDur > 15)
{
    PingpongGameManager.singleton.gameChieventState = 2;
    achieventTrigger.Trigger();
    SuperController.LogMessage("加油!");
}
//......

简单demo演示
https://www.zhihu.com/video/1454999544165072896
由于篇幅原因,除了上面这些,还有一些知识点没能讲到。等到以后有时间再写吧。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-12-23 12:12 , Processed in 0.096000 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表