本例子是通过UGUI实现
话不多说 我们直接看最终效果先
NICE!! 这 这就是!就是大厂的感觉 !!!
好了 下面就是教程 或者可以直接看最后的代码部分
首先 我直接使用unity中的Ui贴图来做了一个虚拟摇杆的样式 大概是这个样子啦
然后就我思考一下 首先应当实现摇杆要出现在点击后的位置 然后呢中心的这个点只能在圆内范围移动
那首先思路是 先记录下 鼠标点击后的位置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);
}
}
首先我们创建出一个3A级的人物模型
以防一会看不出它的头的朝向我为他添加了一个坚毅的鼻子。
好 然后开始思考环节,既然在转盘里我们已经求出了向量方向那么 只需要在玩家类里面 实现一个传入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);
}
好 万事大吉 感觉毫无问题 让我们看看实际情况
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);
}
}
有点懒 还没上传~