Unity制作3D场景的脑电运动想象范式(左右手抓握)
使用Unity制作3D场景中的运动想象范式
3D技术可以创建出立体的图像和环境,给用户带来更加真实和沉浸式的体验,本文介绍了一种可控的左右手运动的3D场景范式的设计流程,用于被试在3D场景下完成运动想象脑电信号数据的采集。
目录
1.制作动画
1.1导入模型
1.2记录关键帧
2.制作范式
2.1 模型导入与设置
2.2 代码相关
2.3完整参数选择设置
制作左右手运动想象的范式,想要在unity中得到会动的场景,当然要制作出有动画的模型。这里使用C4D完成对手掌的建模、动作的制作。关于肢体骨骼的绑定与建立,详细教程在我另一篇博客里有介绍,这里不在过多赘述:
https://wyz99666.blog.csdn.net/article/details/128507248?spm=1001.2014.3001.5502
本文使用的手掌模型这里给出:
链接:https://pan.baidu.com/s/124-XAsYDsobkvbn01bE7tg?pwd=7gok
提取码:7gok
选择文件中下面的.c4d模型,在C4D中打开左手或者右手的手掌原始静止模型,如下图所示:

打开模型后,C4D中右侧布局可以看到手掌的各个关节信息,需要使用这些关节来制作对应的动画。
制作动画需要使用到关键帧,也就是在两个帧中间C4D可以记录模型运动的轨迹或者角度,从而生成动画,当从C4D导出fbx格式或者其他格式的模型时,模型会包含我们设置的动画。接着就可以在unity或者别的场景搭建软件中使用这些动画,然后就可以制作范式啦。
①:

②:

③:

完成这步操作后,手指运动的过程就记录在0-20的关键帧中了,点击播放按钮,食指在0-20帧间就可以运动了。这里具体每个关节执行的步骤不再演示(可以根据自己所需的不同动作自行设置角度),最后得到完整的抓握动作如下图所示:

完成这步操作之后,导出文件为fbx格式就可以得到带有动画的手掌模型了,下一步就可以在unity中使用模型完成范式搭建啦。具体操作如下图

注意在导出设置中最好按下面的选项设置,特别是这个细分面,如果不勾选,在unity中得到的手臂边界会很带有锯齿、比较粗糙。

在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中模型上即可,如下图所示。

using UnityEngine;
using System.Collections;public class left_offline : MonoBehaviour
{private Animator Anim;void Start(){Anim = GetComponent<Animator>();}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 = GetComponent<Animator>();}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);}
}
然而每次运动想象实验可能需要的试次和实验间隔都会不一样,这就需要设置一个开始的参数选择界面,在开始前设置好实验试次以及试次之间的间隔时间,这个时间包括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.GetComponent<CanvasGroup>();// 缓存 left_offline 和 right_offline 实例leftOfflineScript = FindObjectOfType<left_offline>();rightOfflineScript = FindObjectOfType<right_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通信给你,用于对其余设备通信左右手执行的信息,通知设备开始打标签。
最后只需要将摄像头移动到手臂上方调整角度,范式就搭建完成啦。
最后运行的视角是这样的:
开始界面:

左手运动:

右手运动:
更复杂的实验场景就需要读者自行设计并实现啦。
相关文章:
Unity制作3D场景的脑电运动想象范式(左右手抓握)
使用Unity制作3D场景中的运动想象范式 3D技术可以创建出立体的图像和环境,给用户带来更加真实和沉浸式的体验,本文介绍了一种可控的左右手运动的3D场景范式的设计流程,用于被试在3D场景下完成运动想象脑电信号数据的采集。 目录 1.制作动画…...
python23-常用的第三方库01:request模块-爬虫
requests 模块是 Python 中的一个第三方库,用于发送 HTTP 请求。 它提供了一个简单且直观的 API,使得发送网络请求和解析响应变得非常容易。requests 模块支持各种 HTTP 方法,如 GET、POST、PUT、DELETE 等,并且具有处理 cookies…...
CAT3D: Create Anything in 3D with Multi-View Diffusion Models 论文解读
24年5月的论文,上一版就是ReconFusion 目录 一、概述 二、相关工作 1、2D先验 2、相机条件下的2D先验 3、多视角先验 4、视频先验 5、前馈方法 三、Method 1、多视角扩散模型 2、新视角生成 3、3D重建 一、概述 该论文提出一种CAT3D方法,实现…...
持续学习入门
参考视频(一) 【学无止境:深度连续学习】 背景 更新新的数据时,数据异步输入,会有灾难性遗忘 现有解决策略 (1)引入正则约束(2)设计合适的动态模型架构 ÿ…...
天猫推荐数据集实践
参考自 https://github.com/xufengtt/recom_teach_code,学习记录。 环境配置(maxcomputedataworks) 下载天猫推荐数据集;开启 aliyun 的 maxcompute,dataworks,pai;使用 odpscmd 上传本地数据…...
《Vue3实战教程》33:Vue3路由
如果您有疑问,请观看视频教程《Vue3实战教程》 路由 客户端 vs. 服务端路由 服务端路由指的是服务器根据用户访问的 URL 路径返回不同的响应结果。当我们在一个传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML&…...
【大模型系列】MultiUI(2024.11)
Paper:https://arxiv.org/pdf/2410.13824Github:https://neulab.github.io/MultiUI/Author:Junpeng Liu et al., 卡内基梅隆 核心1: 先基于text-based LLMs获取网页的accessibility tree(辅助功能树,https://200t.w3c…...
「Mac畅玩鸿蒙与硬件52」UI互动应用篇29 - 模拟火车票查询系统
本篇教程将实现一个模拟火车票查询系统,通过输入条件筛选车次信息,并展示动态筛选结果,学习事件处理、状态管理和界面展示的综合开发技巧。 关键词 条件筛选动态数据展示状态管理UI交互查询系统 一、功能说明 模拟火车票查询系统包含以下功…...
Dubbo 核心知识全解析:原理、流程与关键机制
1.说说一次 Dubbo 服务请求流程? Dubbo 是一个分布式服务框架,它简化了基于 SOA(面向服务架构)的应用程序的开发。一次典型的 Dubbo 服务请求流程如下: 服务提供者启动: 服务提供者启动后,会向注册中心注册…...
时间序列预测算法---LSTM
目录 一、前言1.1、深度学习时间序列一般是几维数据?每个维度的名字是什么?通常代表什么含义?1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路?1.4、RNN存在哪些问题? 二、…...
二十三种设计模式-建造者模式
建造者模式(Builder Pattern)是一种创建型设计模式,它提供了一种分步骤构建复杂对象的方法。这种模式允许你通过相同的创建过程构建不同的表示。建造者模式将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的对象…...
MarkDown 的 mermaid gantt(甘特图)、mermaid sequenceDiagram (流程图) 语法解析和应用
简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 MarkDown 的 mermaid gantt、mermaid sequenceDiagram 语法解析和应用前言mermaid gan…...
git submodule的使用:将别人的git仓库作为自己的子仓库
git的基本操作在该篇中展示:git的基本操作在日常开发中,我们经常会碰到需要将别人的仓库作为自己的子仓库来进行开发。下面将介绍具体将如何操作。 1、添加Submodule至自己的git仓库 1.1、创建自己的Git仓库 (1)在github中创建自…...
Springboot 下载附件
GetMapping("/download") public void download(RequestParam String fileId, HttpServletResponse response) throws IOException {// 查询文件信息SysFileEntity sysFileEntity fileService.queryFileById(fileId);response.setContentType("application/oct…...
MySQL 延迟复制:确保数据安全与系统稳定的秘诀
MySQL 延迟复制:确保数据安全与系统稳定的秘诀 在 MySQL 主从复制架构中,数据的同步通常是实时的。然而,在一些特定场景下,我们可能不希望从库立刻同步主库的所有更新。特别是在高风险操作或者主库出现故障时,实时复制…...
ELK 使用教程采集系统日志 Elasticsearch、Logstash、Kibana
前言 你知道对于一个系统的上线考察,必备的几样东西是什么吗?其实这也是面试中考察求职者,是否真的做过系统开发和上线的必备问题。包括:服务治理(熔断/限流) (opens new window)、监控 (opens new window)和日志,如果…...
python实现自动登录12306抢票 -- selenium
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 python实现自动登录12306抢票 -- selenium 前言其实网上也出现了很多12306的代码,但是都不是最新的,我也是从网上找别人的帖子,看B站视频&…...
使用Diffusion Models进行图像超分辩重建
Diffusion Models专栏文章汇总:入门与实战 前言:图像超分辨率重建是一个经典CV任务,其实LR(低分辨率)和 HR(高分辨率)图像仅在高频细节上存在差异。通过添加适当的噪声,LR 图像将变得与其 HR 对应图像无法区分。这篇博客介绍一种方式巧妙利用这个规律使用Diffusion Mod…...
吾杯网络安全技能大赛——Misc方向WP
吾杯网络安全技能大赛——Misc方向WP Sign 题目介绍: 浅浅签个到吧 解题过程: 57754375707B64663335376434372D333163622D343261382D616130632D3634333036333464646634617D 直接使用赛博橱子秒了 flag为 WuCup{df357d47-31cb-42a8-aa0c-6430634ddf4a} 原神启动…...
Web安全 - “Referrer Policy“ Security 头值不安全
文章目录 概述原因分析风险说明Referrer-Policy 头配置选项1. 不安全的策略no-referrer-when-downgradeunsafe-url 2. 安全的策略no-referreroriginorigin-when-cross-originsame-originstrict-originstrict-origin-when-cross-origin 推荐配置Nginx 配置示例 在 Nginx 中配置 …...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
抖音增长新引擎:品融电商,一站式全案代运营领跑者
抖音增长新引擎:品融电商,一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中,品牌如何破浪前行?自建团队成本高、效果难控;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
数据结构:泰勒展开式:霍纳法则(Horner‘s Rule)
目录 🔍 若用递归计算每一项,会发生什么? Horners Rule(霍纳法则) 第一步:我们从最原始的泰勒公式出发 第二步:从形式上重新观察展开式 🌟 第三步:引出霍纳法则&…...
