【Unity-学习-010】Unity + ReadSense D435 + Nuitrack 人体识别

如题:Unity + ReadSense D435 + Nuitrack 人体识别,

现在的功能有:

  1. 识别左右半转身
  2. 识别行走
  3. 日后更新。。。。

脚本:GestureManager.cs 用于检测动作的脚本。

using Intel.RealSense;
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Configuration;
using UnityEngine.Events;


    public enum GestureMode
    {
        Face = 0,
        Back = 1,
    }

    public delegate void Motion();
    [Serializable]
    public class TextureEvent : UnityEvent<Texture> { }

    public class GestureManager : MonoBehaviour
    {
        /// <summary>
        /// 检测模式
        /// </summary>
        public GestureMode gestureMode = GestureMode.Face;

        /// <summary>
        /// 单例
        /// </summary>
        static GestureManager instance;
        public static GestureManager Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = FindObjectOfType<GestureManager>();
                    if (instance == null)
                    {
                        GameObject container = new GameObject();
                        container.name = "GestureManager";
                        instance = container.AddComponent<GestureManager>();
                    }
                    DontDestroyOnLoad(instance);
                }
                return instance;
            }
        }

        /// <summary>
        /// 左转 
        /// </summary>
        public event Motion onTurnLeft;
        /// <summary>
        /// 右转
        /// </summary>
        public event Motion onTurnRight;
        /// <summary>
        /// 立正
        /// </summary>
        public event Motion onTurnStraight;
        /// <summary>
        /// 移动
        /// </summary>
        public event Motion onMovement;

        /// <summary>
        /// 显示图片的 事件
        /// </summary>
        public TextureEvent rawImage;

        /// <summary>
        /// 移动延迟时间
        /// </summary>
        private float movementCacheTime = 0.5f;

        public float MovementCacheTime { get => movementCacheTime; set => movementCacheTime = value; }


        /// <summary>
        /// 计时器
        /// </summary>
        private float counter = 0;

        /// <summary>
        /// 单例
        /// </summary>
        private nuitrack.Skeleton skeleton;

        private void Start()
        {
            if (rawImage != null)
            {
                NuitrackManager.onColorUpdate += (frame) =>
                {
                    rawImage.Invoke(frame.ToTexture2D());
                };
            }

        }


        void Update()
        {
            if (CurrentUserTracker.CurrentUser == 0)
            {
                return;
            }
            skeleton = CurrentUserTracker.CurrentSkeleton;

            Movement(skeleton);
        }

        [HideInInspector]
        public float waistHight = 0;
        /// <summary>
        /// 移动判断
        /// </summary>
        /// <param name="skeleton"></param>
        private void Movement(nuitrack.Skeleton skeleton)
        {
            #region 旋转

            Quaternion di = skeleton.GetJoint(nuitrack.JointType.Neck).ToQuaternion();
            float dot = UnityEngine.Quaternion.Dot(UnityEngine.Quaternion.LookRotation(Vector3.right), di);

            switch (gestureMode)
            {
                case GestureMode.Face:
                    if (dot > 0.85f)
                    {
                        onTurnRight?.Invoke();
                    }
                    else if (dot < 0.35f)
                    {
                        onTurnLeft?.Invoke();
                    }
                    else
                    {
                        onTurnStraight?.Invoke();
                    }
                    break;
                case GestureMode.Back:
                    if (dot > 0.85f)
                    {
                        onTurnLeft?.Invoke();
                    }
                    else if (dot < 0.35f)
                    {
                        onTurnRight?.Invoke();
                    }
                    else
                    {
                        onTurnStraight?.Invoke();
                    }
                    break;
            }
            #endregion
            #region 移动
            float L_Hand = skeleton.GetJoint(nuitrack.JointType.LeftHand).ToVector3().y;
            float R_Hand = skeleton.GetJoint(nuitrack.JointType.RightHand).ToVector3().y;

            //手>0 膝盖>-500  摄像机安装方式高度:保持双手双臂放松下垂时,手腕上方5cm高度
            //抬左手右脚 和 抬右手左脚
            if ((L_Hand > waistHight && R_Hand > waistHight))
            {
                counter = movementCacheTime;
            }
            if (counter >= 0)
            {
                counter -= Time.deltaTime;
                onMovement?.Invoke();
            }
            #endregion
        }

        /// <summary>
        /// 校准
        /// </summary>
        public void Calibration()
        {
            if (skeleton == null) return;
            waistHight = skeleton.GetJoint(nuitrack.JointType.Waist).ToVector3().y;
        }

    }

面板设置:

脚本:PlayerMovement.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using tracker;

public class PlayerMovement : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        rig = GetComponent<Rigidbody>();
        if (rig == null)
        {
            rig = gameObject.AddComponent<Rigidbody>();
        }
        GestureManager.Instance.onTurnRight += Instance_onTurnRight;
        GestureManager.Instance.onTurnLeft += Instance_onTurnLeft;
        GestureManager.Instance.onMovement += Instance_onMovement;
        GestureManager.Instance.onTurnStraight += Instance_onTurnStraight;
    }

    public float moveSpeed = 10;
    public float rotaSpeed = 10;
    public bool turning = false;
    public bool moveing = false;

    private Rigidbody rig;

    private void Instance_onTurnStraight()
    {
        if (turning || moveing)
        {

        }
        else
        {
            //做一些只有在立正时才做的事情  比如 添加手势控制功能 操作UI等
        }
    }

    /// <summary>
    /// 移动
    /// </summary>
    private void Instance_onMovement()
    {
        Moveing(1, moveSpeed);
    }

    /// <summary>
    /// 旋转——Right
    /// </summary>
    private void Instance_onTurnRight()
    {
        Turning(1, rotaSpeed);
    }
    /// <summary>
    /// 旋转——Left
    /// </summary>
    private void Instance_onTurnLeft()
    {
        Turning(-1, rotaSpeed);
    }

    /// <summary>
    /// 旋转
    /// </summary>
    private void Turning(int dir, float speed)
    {
        float angel = transform.localRotation.eulerAngles.y;
        transform.localRotation = Quaternion.Lerp(transform.localRotation, Quaternion.Euler(0, angel += (speed * dir), 0), Time.deltaTime * speed);
    }

    /// <summary>
    /// 移动
    /// </summary>
    /// <param name="dir">方向</param>
    /// <param name="speed">速度</param>
    private void Moveing(int dir, float speed)
    {
        rig.MovePosition(transform.localPosition += transform.forward * speed * Time.deltaTime);
    }
}

代码比较简单,就不写注释了。注意刚体设置。

脚本:BoxControl.cs 摄像机跟随脚本,可以实现碰撞缩进。

using UnityEngine;
/// <summary>
/// 脚本附着在 CameraBox上
/// </summary>
public class BoxControl : MonoBehaviour
{
    public Transform target;
    private Transform mainCam;
    private float disT2B;

    // Use this for initialization
    void Start()
    {
        mainCam = GameObject.FindWithTag("MainCamera").transform;
        disT2B = Vector3.Distance(target.position, transform.position);//记录target和CameraBox之间的初始距离
    }

    // Update is called once per frame
    void LateUpdate()
    {
        Modulation();
        //相机个cameraBox做插值
        mainCam.position = Vector3.Lerp(mainCam.position, transform.position, 0.1f);
        //相机始终看向角色正前方
        mainCam.LookAt(target.position);
    }
    RaycastHit hit;//声明一个检测碰撞的对象
    float disT2H;

    void Modulation()
    {
        Vector3 rayDir = -target.forward.normalized;//获取 target 指向 相机盒子 方向的单位向量

        //检测射线碰撞并填充 hit 
        if (Physics.Raycast(target.position, rayDir, out hit, disT2B))
        {
            disT2H = hit.distance;
        }
        else
        {
            disT2H = disT2B;
        }
        transform.position = disT2H * rayDir + target.position;
    }

}

其中 CameraBox 是Player 的子物体。具体设置方法见网址:http://www.narkii.com/club/thread-412883-1.html

也是我写的,有时间誊到csdn上。

实现的效果:

Unity + ReadSense D435 + Nuitrack 人体动作识别

 

 

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ThursdayGame

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值