Unity中实现摇杆操作人物

UGUI实现人物移动摇杆

  • 摇杆Ui实现
  • 通过摇杆控制人物
  • 所有实现代码
  • Git下载地址

本例子是通过UGUI实现
话不多说 我们直接看最终效果先
Unity中实现摇杆操作人物_第1张图片
NICE!! 这 这就是!就是大厂的感觉 !!!
好了 下面就是教程 或者可以直接看最后的代码部分

摇杆Ui实现

首先 我直接使用unity中的Ui贴图来做了一个虚拟摇杆的样式 大概是这个样子啦
Unity中实现摇杆操作人物_第2张图片
然后就我思考一下 首先应当实现摇杆要出现在点击后的位置 然后呢中心的这个点只能在圆内范围移动
那首先思路是 先记录下 鼠标点击后的位置beginPos 然后 再在每一帧去计算当前手指位置 和点击位置之间的一个向量方向关系(vector) 接着再计算当前手指位置和起始位置的距离(diatance) 然后再与方向相乘 就可以得出小圆点 应该要出现的位置了~ 同时通过Math.clamp方法去限制distance的长度 就能保证小圆圈只能在指定距离里面移动
好 那贴上代码就是


    public Image rocker; //摇杆点点物体 父物体我们通过.parent取得
    private Vector3 beginPos;//鼠标点下后的起始位置

	public void Updata()
	{
		Rocker();
	}
    public void Rocker()
    {
        if (Input.GetMouseButtonDown(0))
        {
        	//隐藏着的摇杆盘显示出来
            rocker.transform.parent.gameObject.SetActive(true);
            beginPos = Input.mousePosition;
            //让摇杆盘位置等于鼠标点击的位置
            rocker.transform.parent.transform.position = beginPos;
        }else if (Input.GetMouseButton(0))
        {
        	//通过运算并normalized后求出两点之间的方向
            Vector3 vector = Input.mousePosition - beginPos;
            vector = vector.normalized;
         
         	//这里先是求出两点之间的距离 并且同mathf.Clamp进行一个范围的限制,然后在把这个距离与vector 两点之间的方向相乘 得出点点所在的位置
            rocker.transform.localPosition = Mathf.Clamp(Vector3.Distance(beginPos, Input.mousePosition), 0, 120f)*vector;            
            
        }
        else if (Input.GetMouseButtonUp(0))
        {
        	//鼠标抬起后 点点回到中间 关闭摇杆盘 初始化beginPos
            beginPos = Vector3.zero;
            rocker.transform.localPosition = Vector3.zero;
            rocker.transform.parent.gameObject.SetActive(false);
        }
    }

好 然后我们看看效果 Nice! 已经开始有大厂的感觉了!
Unity中实现摇杆操作人物_第3张图片

通过摇杆控制人物

首先我们创建出一个3A级的人物模型

Unity中实现摇杆操作人物_第4张图片
以防一会看不出它的头的朝向我为他添加了一个坚毅的鼻子。
好 然后开始思考环节,既然在转盘里我们已经求出了向量方向那么 只需要在玩家类里面 实现一个传入Vector3的方法就可以实现人物向指定方向移动和旋转的方法 ,毕竟我们是想人物移动和朝向的方向与我们摇杆的一致对吧。

    public void Move(Vector3 vector)
    {
    	//倘若点下去后 没有移动手指 直接不处理
        if (vector == Vector3.zero) return;

		//再次把向量归一化
        vector = vector.normalized;
		//然后玩家的位置加上方向与距离的乘积,让玩家向对应方向移动 也可以通过rigibody.addfource(Vector3.forward*vector) 来施加方向力
        transform.position += vector*0.1f;
		//通过向量方向 计算出当前向量方向以0,0为原点(0度)之间的夹角 求出角色应当朝向的位置
        float angleOfLine = Mathf.Atan2(vector.x, vector.z)*180/Mathf.PI;
		//更新角色y轴方向
        transform.rotation = Quaternion.Euler(0, angleOfLine, 0);
    }

好 万事大吉 感觉毫无问题 让我们看看实际情况
Unity中实现摇杆操作人物_第5张图片
OH 漏! 为什么方向不对劲!! 还有为什么它是飞起来了
这里是有两个原因造成的 我们先分析一下 为什么会飞起来
让我们回顾一下Ui上传入的vector

          controller.Move(vector);
          在这里的vector 实际上是(数值,数组,0)
          鼠标位置所占用的位置信息是前两位 x,y
          但是在游戏中y是负责人物高度信息的 所以左右是x,前后是z
          既然找出问题 那样只要把数值 y替换到z就好了 如下
   		  controller.Move(new Vector3(vector.x, 0, vector.y));

但是这也只解决了其中一个问题 还有就是移动起来的方向和操作的方向不一致呢~
这个是因为我们的镜头是处于45°角的原因 所以实际上我们移动的位置确实和实际方向是一样的 只是镜头的缘故 所以看起来是不对。 那怎么解决呢? 这时候只需要把传入的方向向量进行一个简单的旋转就好了 既然我们镜头旋转了45度 那么我向量也旋转45°就好了呀
根据公式x1=xcosθ1+ysinθ1, y1=-xsinθ1+ycosθ1, z1=z
那 既然我们y要替换成z就是
Mathf.Cos(-45) * vector.x + Mathf.Sin(-45) * vector.y, 0, -Mathf.Sin(-45) * vector.x + Mathf.Cos(-45) * vector.y
好 那完整的调用方法就是

controller.Move(new Vector3(Mathf.Cos(-45) * vector.x + Mathf.Sin(-45) * vector.y, 0, Mathf.Sin(45) * vector.x + Mathf.Cos(45) * vector.y));

但是有个奇怪的问题就是 当我用来这个方法后 实际上玩家最终向上直行的方向是57° 和预想中的45°有偏差 所以最后调整了镜头y角度为-57°(希望有大大能够告知为啥咯)

这 这就是农药!我已经能看出农药的影子了!!

所有实现代码

最后这里贴出的就是全部的实现代码了
RockTool

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RockerTool : MonoBehaviour {

    public Image rocker;
    private Vector3 beginPos;
    private PlayerController controller;
	// Use this for initialization
	void Start () {
	    


        controller = GameObject.FindObjectOfType();


	}

    private void Update()
    {
        Rocker();
    }
    public void Rocker()
    {
        if (Input.GetMouseButtonDown(0))
        {
            rocker.transform.parent.gameObject.SetActive(true);
            beginPos = Input.mousePosition;
            rocker.transform.parent.transform.position = beginPos;
        }else if (Input.GetMouseButton(0))
        {
            Vector3 vector = Input.mousePosition - beginPos;
            vector = vector.normalized;
            rocker.transform.localPosition = Mathf.Clamp(Vector3.Distance(beginPos, Input.mousePosition), 0, 120f)*vector;
            controller.Move(new Vector3(Mathf.Cos(-45) * vector.x + Mathf.Sin(-45) * vector.y, 0, Mathf.Sin(45) * vector.x + Mathf.Cos(45) * vector.y));
            //controller.Move(new Vector3(vector.x, 0, vector.y));
            //
        }
        else if (Input.GetMouseButtonUp(0))
        {
            beginPos = Vector3.zero;
            rocker.transform.localPosition = Vector3.zero;
            rocker.transform.parent.gameObject.SetActive(false);
        }
    }
}

PlayerController

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

public class PlayerController : MonoBehaviour {
    public void Move(Vector3 vector)
    {
        if (vector == Vector3.zero) return;

        vector = vector.normalized;

        transform.position += vector*0.1f;

        float angleOfLine = Mathf.Atan2(vector.x, vector.z)*180/Mathf.PI;

        transform.rotation = Quaternion.Euler(0, angleOfLine, 0);
    }
}

Git下载地址

有点懒 还没上传~

你可能感兴趣的:(Unity)