网站优化设计方案,国外网站 国内做镜像,公司网站自己可以做吗,个人网站建立策划书前言使用Unity制作3D场景中的运动想象范式
3D技术可以创建出立体的图像和环境#xff0c;给用户带来更加真实和沉浸式的体验#xff0c;本文介绍了一种可控的左右手运动的3D场景范式的设计流程#xff0c;用于被试在3D场景下完成运动想象脑电信号数据的采集。
目录 1.制作动画…使用Unity制作3D场景中的运动想象范式
3D技术可以创建出立体的图像和环境给用户带来更加真实和沉浸式的体验本文介绍了一种可控的左右手运动的3D场景范式的设计流程用于被试在3D场景下完成运动想象脑电信号数据的采集。
目录 1.制作动画 1.1导入模型 1.2记录关键帧 2.制作范式 2.1 模型导入与设置 2.2 代码相关 2.3完整参数选择设置 1.制作动画 1.1导入模型 制作左右手运动想象的范式想要在unity中得到会动的场景当然要制作出有动画的模型。这里使用C4D完成对手掌的建模、动作的制作。关于肢体骨骼的绑定与建立详细教程在我另一篇博客里有介绍这里不在过多赘述 https://wyz99666.blog.csdn.net/article/details/128507248?spm1001.2014.3001.5502 本文使用的手掌模型这里给出 链接https://pan.baidu.com/s/124-XAsYDsobkvbn01bE7tg?pwd7gok 提取码7gok 选择文件中下面的.c4d模型在C4D中打开左手或者右手的手掌原始静止模型如下图所示
打开模型后C4D中右侧布局可以看到手掌的各个关节信息需要使用这些关节来制作对应的动画。 制作动画需要使用到关键帧也就是在两个帧中间C4D可以记录模型运动的轨迹或者角度从而生成动画当从C4D导出fbx格式或者其他格式的模型时模型会包含我们设置的动画。接着就可以在unity或者别的场景搭建软件中使用这些动画然后就可以制作范式啦。 1.2 记录关键帧 如下图所示红圈圈住的地方有关键帧的字样点击后C4D会自动记录你对当前模型操作的过程 ①首先点击红色按钮点击后展示界面边框会变成红色比如想要的效果是在0-20帧之间执行手掌的抓取动作②则将帧数刻度移动到20的地方③然后选中食指的根关节并拖动关节某一个轴旋转一定的角度具体操作如下图①②③所示 ① ② ③ 完成这步操作后手指运动的过程就记录在0-20的关键帧中了点击播放按钮食指在0-20帧间就可以运动了。这里具体每个关节执行的步骤不再演示可以根据自己所需的不同动作自行设置角度最后得到完整的抓握动作如下图所示 完成这步操作之后导出文件为fbx格式就可以得到带有动画的手掌模型了下一步就可以在unity中使用模型完成范式搭建啦。具体操作如下图 注意在导出设置中最好按下面的选项设置特别是这个细分面如果不勾选在unity中得到的手臂边界会很带有锯齿、比较粗糙。 2.制作范式 2.1 模型导入与设置 在unity中新建一个3D项目并导入刚刚导出的fbx模型。这里的带有动画的fbx模型不在给出读者可以自行设计并得到自己的模型。结果如下图这里我新建了Model文件夹并导入四个带动画的model分别是左手抓握、右手抓握、左手静止、右手静止其中静止的模型也是带有动画的这个动画中关节移动的角度非常小所以忽略不计为静止状态这么设置是为了后续的动作连贯。 将左右手的模型拖入场景中在Hierarchy中可以看到两个模型。 接着针对每个模型需要设置一个动画控制器Animator Controller用来控制模型动画的执行也就是使得手掌的抓握是可以控制的如下图我新建了一个Control文件夹并右键新建两个Animator Controller分别命名为right、left来控制左右手的动画。 双击Animator Controller进入设置页面这里我设置了一个参数left_offline用来控制手掌动画的执行参数在新增的时候选择是bool类型的。 在Base layer栏将左手静止模型和左手抓握模型中的animator都拖入Base layer栏中分别命名为左手静止和左手抓握并在这两个动画直接右键建立连接 建立完连接后点击连接两个动画的线如从左手静止到左手抓握在inspector栏中的Conditions中添加刚刚新增的参数并设置当left_offline为true时左手抓握的动作执行。同理从左手抓握到左手静止的Conditions设置成left_offline为false具体设置如下图 同理也可以完成对右手控制器的设置。完成以上的设置后我们通过程序控制模型执行动作的目的已经完成一半了在动画控制器的帮助下我们已经完成了对模型的设置也就是当参数left_offline为true时执行抓握动作当left_offline为false时抓握动作结束进而完成静止动作这样就可以实现运动想象中手掌运动的cue效果了。最终我们的设置如下图所示。 将对应的Animator Controller绑定到对应的scene中模型上即可如下图所示。 2.2 代码相关 在完成场景以及动画的控制设置后如何通过来控制动画执行呢 这里使用C#脚本在Asset文件夹下新建了Script文件其中首先新建两个脚本命名为left_offline.cs和right_offline.cs将这两个文件分别拖到场景的左手抓握和右手抓握模型下如图所示 这两个文件决定了手掌抓握动作的执行这里我简单举例具体实验所需的执行频率设置由另一个文件drop.cs设置决定。 如left_offline.cs using UnityEngine;
using System.Collections;public class left_offline : MonoBehaviour
{private Animator Anim;void Start(){Anim GetComponentAnimator();}public void UpdateAnimation(){if (Anim ! null){Anim.SetBool(left_offline, true);StartCoroutine(ResetBoolAfterDelay(2f));}else{Debug.Log(Animator 未正确引用);}}IEnumerator ResetBoolAfterDelay(float delay){yield return new WaitForSeconds(delay);Anim.SetBool(left_offline, false);}
}
在start函数中获取了左手抓握模型的动画对象并命名为Anim在UpdateAnimation函数中对参数赋值如对动画控制器中的left_offline赋值为true并设置携程函数ResetBoolAfterDelay当赋值完成2秒后再将参数left_offline设置为false这个脚本每执行一次update即可完成一次左手动作的cue。右手的控制脚本同理这里不再赘述直接给出代码
using UnityEngine;
using System.Collections;public class right_offline : MonoBehaviour
{private Animator Anim;void Start(){Anim GetComponentAnimator();}public void UpdateAnimation(){if (Anim ! null){Anim.SetBool(right_offline, true);StartCoroutine(ResetBoolAfterDelay(2f));}else{Debug.Log(Animator 未正确引用);}}IEnumerator ResetBoolAfterDelay(float delay){yield return new WaitForSeconds(delay);Anim.SetBool(right_offline, false);}
} 2.3 完整参数选择设置 然而每次运动想象实验可能需要的试次和实验间隔都会不一样这就需要设置一个开始的参数选择界面在开始前设置好实验试次以及试次之间的间隔时间这个时间包括cue、被试运动想象以及休息时间。所以这里需要在unity场景中设置一个选择界面如下图所示 这里在场景中新建了一个画布。画布中包括两个下拉框分别为试次数量和试次间隔时间通过此模块用户可以根据自己实验需要设置不同参数画布中包括的内容如下图 其中包括两个黑色背景图、两个text试次数量、试次时间、两个下拉框、一个确认按钮 那么需要新建一个脚本用于获取确认按钮提交的下拉框内的数据并执行相应数量和相应时间间隔的左右手抓取动作。这里给出drop.cs脚本如下只需要将drop.cs拖动到画布的Inspector中即可
using System.Collections;
using System.Collections.Generic;
using UnityEngine;using UnityEngine.UI;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System;public class test : MonoBehaviour
{public Dropdown trialDropdown; // 绑定 Dropdown(Trial)public Dropdown internalDropdown; // 绑定 Dropdown(Internal)public Button submitButton; // 绑定 SubmitButtonpublic bool gameEnded false;CanvasGroup canvasGroup;private left_offline leftOfflineScript;private right_offline rightOfflineScript;void Start(){// 确保组件已绑定if (trialDropdown null || internalDropdown null || submitButton null){Debug.LogError(Dropdowns or Button are not assigned in the Inspector.);return;}// 为按钮添加点击事件submitButton.onClick.AddListener(SubmitValues);canvasGroup transform.GetComponentCanvasGroup();// 缓存 left_offline 和 right_offline 实例leftOfflineScript FindObjectOfTypeleft_offline();rightOfflineScript FindObjectOfTyperight_offline();if (leftOfflineScript null || rightOfflineScript null){Debug.LogError(Missing left_offline or right_offline script instances in the scene.);}}void SubmitValues(){// 获取 Dropdown 的选定值string trialValue trialDropdown.options[trialDropdown.value].text;string internalValue internalDropdown.options[internalDropdown.value].text;// 调试信息Debug.Log($Trial Selected: {trialValue});Debug.Log($Internal Selected: {internalValue});int num int.Parse(trialValue);int Internal int.Parse(internalValue);canvasGroup.alpha 0;canvasGroup.interactable false;canvasGroup.blocksRaycasts false;// 将值发送到后端StartCoroutine(DoTrials(num, Internal));}IEnumerator DoTrials(int num, int interval){for (int i 0; i num; i){int hand i % 2; // 0 for left, 1 for rightif (hand 0){if (leftOfflineScript ! null)leftOfflineScript.UpdateAnimation();}else{if (rightOfflineScript ! null)rightOfflineScript.UpdateAnimation();}// 等待指定的间隔yield return new WaitForSeconds(interval);}gameEnded true;}void Update(){// 检查游戏是否结束if (gameEnded){// 结束游戏Debug.Log(Game Ended.);Application.Quit();}}
}
这里drop.cs脚本给的是交替执行左右手抓取运动读者可以自行改进改成随机执行同时考虑到打标签的需要读者可以在这个脚本中添加socket通信给你用于对其余设备通信左右手执行的信息通知设备开始打标签。 最后只需要将摄像头移动到手臂上方调整角度范式就搭建完成啦。 最后运行的视角是这样的 开始界面 左手运动 右手运动 更复杂的实验场景就需要读者自行设计并实现啦。