Unity MARS插件:实现IProvidesMarsBodyTracking时BodyAdded参数传递疑问
Unity MARS 人体追踪实现疑问
我正尝试使用Unity MARS插件提供的IProvidesMarsBodyTracking API实现人体追踪,以下是继承该接口与MonoBehaviour的脚本:
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.MARS.Providers; using System; using Unity.MARS.Data; public class BodyTrackManager : MonoBehaviour, IProvidesMarsBodyTracking { public event Action<IMarsBody> BodyAdded; public event Action<IMarsBody> BodyUpdated; public event Action<IMarsBody> BodyRemoved; [SerializeField] GameObject marsBody; public void ConnectSubscriber(object obj) { throw new NotImplementedException(); } public void GetBodies(List<IMarsBody> bodies) { BodyAdded += BodyTrackManager_BodyAdded; Debug.Log("Test"); } private void BodyTrackManager_BodyAdded(IMarsBody obj) { marsBody.transform.position = obj.BodyPose.bodyPosition; marsBody.SetActive(true); } public void LoadProvider() { throw new NotImplementedException(); } public void UnloadProvider() { throw new NotImplementedException(); } }
该脚本已挂载到MARS相机,我用一个球体对象作为追踪观测对象,用来查看人体是否被追踪或停止追踪。BodyTrackManager_BodyAdded是注册到BodyAdded事件的自定义方法,但我不清楚应将哪个对象作为该方法的IMarsBody类型参数传入。
问题解析与修正方案
首先明确:IProvidesMarsBodyTracking是提供方接口,它的职责是由Unity MARS底层(或你自定义的追踪逻辑)触发BodyAdded/Updated/Removed事件,你不需要手动传入IMarsBody参数——参数是事件触发者(比如MARS人体追踪底层模块)自动传递的。你的代码目前存在几个关键问题,导致逻辑无法正常工作:
核心问题点
- 接口方法实现错误:
GetBodies的作用是让调用者获取当前所有已追踪人体列表,不是用来注册事件监听的;未实现的ConnectSubscriber、LoadProvider、UnloadProvider必须正确完成逻辑,否则MARS无法识别这个提供方。 - 事件触发逻辑缺失:作为
IProvidesMarsBodyTracking的实现类,你需要自己处理人体检测逻辑,当检测到新人体、状态更新、人体消失时,主动触发对应事件,此时IMarsBody对象是你创建的追踪数据实例。
修正后的脚本示例
using System.Collections; using System.Collections.Generic; using UnityEngine; using Unity.MARS.Providers; using System; using Unity.MARS.Data; public class BodyTrackManager : MonoBehaviour, IProvidesMarsBodyTracking { public event Action<IMarsBody> BodyAdded; public event Action<IMarsBody> BodyUpdated; public event Action<IMarsBody> BodyRemoved; [SerializeField] GameObject marsBody; // 存储已追踪的人体 private Dictionary<int, IMarsBody> trackedBodies = new Dictionary<int, IMarsBody>(); void Awake() { // 注册事件回调 BodyAdded += OnBodyAdded; BodyUpdated += OnBodyUpdated; BodyRemoved += OnBodyRemoved; } public void ConnectSubscriber(object obj) { // 关联MARS订阅者与当前提供方 var subscriber = obj as IMarsBodyTrackingSubscriber; subscriber?.SubscribeBodyTracking(this); } public void GetBodies(List<IMarsBody> bodies) { // 返回当前所有已追踪人体 bodies.Clear(); bodies.AddRange(trackedBodies.Values); } public void LoadProvider() { // 初始化追踪逻辑,比如启动摄像头、加载检测模型 StartCoroutine(SimulateBodyTracking()); } public void UnloadProvider() { // 停止追踪并释放资源 StopCoroutine(SimulateBodyTracking()); trackedBodies.Clear(); } // 模拟人体追踪逻辑(实际项目替换为真实检测代码) private IEnumerator SimulateBodyTracking() { int bodyId = 0; while (true) { // 模拟检测到新人体 if (trackedBodies.Count == 0) { var newBody = new MarsBodyMock(bodyId++, transform.position + Vector3.forward); trackedBodies.Add(newBody.Id, newBody); BodyAdded?.Invoke(newBody); } // 模拟已追踪人体位置更新 else { foreach (var body in trackedBodies.Values) { var mockBody = body as MarsBodyMock; mockBody.UpdatePosition(mockBody.BodyPose.bodyPosition + Vector3.right * 0.1f); BodyUpdated?.Invoke(mockBody); } } yield return new WaitForSeconds(0.5f); } } // 事件回调方法 private void OnBodyAdded(IMarsBody body) { marsBody.transform.position = body.BodyPose.bodyPosition; marsBody.SetActive(true); Debug.Log($"检测到新人体,ID: {body.Id}"); } private void OnBodyUpdated(IMarsBody body) { marsBody.transform.position = body.BodyPose.bodyPosition; Debug.Log($"人体位置更新,ID: {body.Id}"); } private void OnBodyRemoved(IMarsBody body) { marsBody.SetActive(false); Debug.Log($"人体消失,ID: {body.Id}"); } // 自定义IMarsBody实现类,用于存储追踪数据 private class MarsBodyMock : IMarsBody { public int Id { get; private set; } public MarsPose BodyPose { get; private set; } public Dictionary<int, MarsPose> JointPoses { get; private set; } public MarsBodyMock(int id, Vector3 position) { Id = id; BodyPose = new MarsPose(position, Quaternion.identity); JointPoses = new Dictionary<int, MarsPose>(); } public void UpdatePosition(Vector3 newPosition) { BodyPose = new MarsPose(newPosition, BodyPose.rotation); } } }
关键说明
IMarsBody参数不需要手动传入:当你的追踪逻辑检测到人体变化时,创建IMarsBody实例(比如示例中的MarsBodyMock),调用BodyAdded?.Invoke(yourMarsBody),事件回调就会自动接收这个参数。- 若使用MARS官方内置的人体追踪(比如AR Foundation集成的功能),不需要自己实现
IProvidesMarsBodyTracking,直接监听官方提供方的事件即可,只有自定义追踪逻辑时才需要实现该接口。 - 确保在MARS Session中配置了正确的人体追踪提供方,否则自定义提供方无法被识别。
内容的提问来源于stack exchange,提问作者Omkar P
相关产品推荐
相关产品推荐

