二.Unity中使用虚拟摇杆来控制角色移动

上一篇中我们完成了不借助第三方插件实现手游的虚拟摇杆,现在借助这个虚拟摇杆来实现控制角色的移动。

虚拟摇杆实际上就给角色输出方向,类似于键盘的WSAD,也是一个二维坐标,也就是(-1,1)的范围,将摇杆的方向进行归一化传递给角色即可,创建一个名为PlayerManager的脚本,通过Character组件来控制角色的移动。这里在上一篇文章在一. Unity实现虚拟摇杆及屏幕自适应功能,讲述过了,这里拖拽的时候将位移的向量归一化后传递给角色,松手的时候归0.

 mUIEvtListener.OnPointerUpEvent += (eventData =>
            {
                mPointImg.transform.localPosition = mDefaultPos;
                mPointImg.SetActiveState(false);
                mDirImg.transform.localPosition = mDefaultPos;
                PlayerManager.Instance.SetPlayerDir(Vector2.zero);
            });
            mUIEvtListener.OnDragFunc += (eventData =>
            {
                Vector2 dir = eventData.position - mStartPos;
                float length = dir.magnitude;
                PlayerManager.Instance.SetPlayerDir(dir.normalized);
                if (length > mTouchMaxDir)
                {
                    Vector2 clampDir = Vector2.ClampMagnitude(dir, mTouchMaxDir);
                    mPointImg.transform.position = mStartPos + clampDir;
                }
                else
                {
                    mPointImg.transform.position = eventData.position;
                }
            });

在PlayerManager中就是一些常规操作,设置方向,这里用了一个Vector2.SignedAngle的API,其作用就是返回传入向量和目标向量之间的角度,我们设定的目标向量是(0,1)也就是二维向量的正前方,下面画了一张图,应该会很清楚。其中为什么要+mCamTrans.eulerAngles.y,是因为相机是倾斜的照着角色,摄像机于角色之间有一个相对角度,是为了能够确保玩家的移动方向与摄像机视角一致,不论摄像机朝哪个方向,玩家的输入都能按照当前摄像机的视角调整角色的朝向。

在这里插入图片描述

 public class PlayerManager : Component<PlayerManager>
    {
        private const float TouchSpeed = 5;
        private CharacterController mCC;
        private Animator mAnim;
        private Vector2 mDir;
        private Transform mCamTrans;
        private Vector3 mOffset;
        private float mCurAnimSpeed;
        private float mTargerAnimSpeed;
        private const float AccelerSpeed = 5;
        public override void IStart()
        {
            base.IStart();
            mCC = GetComponent<CharacterController>();
            mAnim = GetComponentInChildren<Animator>();
            mCamTrans = Camera.main.transform;
            mOffset = transform.position - mCamTrans.transform.position;
        }

        public override void IUpdate()
        {
            base.IUpdate();
            if (mDir != Vector2.zero)
            {
                SetDir();
                SetMove();
                SetCamera();
            }
        
        }
        /// <summary>
        /// 通过摇杆控制玩家方向
        /// </summary>
        /// <param name="dir"></param>
        public void SetPlayerDir(Vector2 dir)
        {
            if (dir != Vector2.zero)
            {
                mDir = dir;
                SetAnimSpeed(1);
            }
            else
            {
                mDir = Vector2.zero;
                SetAnimSpeed(0);
            }
        }

        private void SetDir()
        {
            float angle = Vector2.SignedAngle(mDir, new Vector2(0, 1)) + mCamTrans.eulerAngles.y;
            transform.eulerAngles = new Vector3(0, angle, 0);
        }

        private void SetMove()
        {
            mCC.Move(transform.forward * Time.deltaTime * TouchSpeed);
        }

        private void SetCamera()
        {
            mCamTrans.transform.position = transform.position - mOffset;
        }
  
    }
}

在这里插入图片描述
最后简单设置一下角色的动画,将Idle和Run进行一个简单的混合,通过插值的形式,让当前的Speed以平缓的过渡到目标值。

   public class PlayerManager : Component<PlayerManager>
    {
        private float mCurAnimSpeed;
        private float mTargerAnimSpeed;
        private const float AccelerSpeed = 5;
       
        public override void IUpdate()
        {
            base.IUpdate();
            if (mDir != Vector2.zero)
            {
                SetDir();
                SetMove();
                SetCamera();
            }
            if (mCurAnimSpeed != mTargerAnimSpeed)
            {
                UpdateAnimFixed();
            }
        }
        private void SetAnimSpeed(float speed)
        {
            mTargerAnimSpeed = speed;
        }

        private void UpdateAnimFixed()
        {
            if (Mathf.Abs(mCurAnimSpeed - mTargerAnimSpeed) > AccelerSpeed)
            {
                mCurAnimSpeed = AccelerSpeed;
            }
            else if(mCurAnimSpeed > mTargerAnimSpeed)
            {
                mCurAnimSpeed -= Time.deltaTime * AccelerSpeed;
            }
            else if(mCurAnimSpeed< mTargerAnimSpeed)
            {
                mCurAnimSpeed += Time.deltaTime * AccelerSpeed;
            }
            mAnim.SetFloat("Speed",mCurAnimSpeed);
        }
     }

测试运行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值