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 中配置 …...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
高分辨率图像合成归一化流扩展
大家读完觉得有帮助记得关注和点赞!!! 1 摘要 我们提出了STARFlow,一种基于归一化流的可扩展生成模型,它在高分辨率图像合成方面取得了强大的性能。STARFlow的主要构建块是Transformer自回归流(TARFlow&am…...
