前言
经过三个小时研究,终于实现Unity 2d的鼠标跟随脚本
目录
autoNavi状态标记变量解决了Follow单脚本鼠标导航的三个bug
功能效果
只要挂载到一个对象上,即可实现鼠标左键跟随
只需要挂载一个脚本,无需任何插件,即可实现点哪走哪!!
当玩家单击鼠标左键时(某些游戏会生成一个箭头动画,指向点击处)人物自动移动到鼠标点击处。
自动导航中人物动画的修正
如果不进行修正,人物将始终处于一个方向,不可改变
为了人物动画的正常显示,还需要获取人物移动的方向向量。
分多种情况,把向量的x,y值传给动画状态集。
一个关键的状态标记变量 autoNavi
//是否处于自动导航状态
public static bool autonavi = false;设置为static,便于UI脚本取消按键时的不必要移动
操作方式的区分
我们要实现的移动
不是"保持鼠标左键按下移动"
而是"单击一次之后,除非被打断,否则要持续移动至目的地"
autoNavi状态标记变量解决了Follow单脚本鼠标导航的三个bug
一、到达目的地之后,仍处于自动导航状态,不能用键盘操控离开标记点,且停止后人物方向与位移方向不匹配
如果到达、则停止这次自动导航,取消标记
if (gameObject.transform.position.x== hitPoint.x && gameObject.transform.position.y== hitPoint.y)
{
clicked = false;
//默认停止显示正面或反面
anim.SetFloat("move X", 0);
anim.SetFloat("move Y", lookDirection.y);
anim.SetFloat("runspeed", 0);
Debug.Log(lookDirection);
}
二、自动导航中无法用键盘改变运动方向
如果在自动前往目的地时,按下了方向键,撤销这次自动导航,取消标记
//如果在自动前往目的地时,按下了方向键,撤销这次自动导航,取消标记
if(Input.GetAxisRaw("Horizontal")!=0||Input.GetAxisRaw("Vertical")!=0)
{
clicked = false;
}
三、自动导航过程中,人物动画的显示与运动方向不匹配
如果这次自动导航未被打断,并且未结束,标记仍然存在,则为运动中的动画状态集赋值,人物的方向在运动结束后回到运动前的朝向
//如果这次自动导航未被打断,并且未结束,标记仍然存在,则为运动中的动画状态集赋值,结束后回到运动前的朝向
if (clicked == true && moveDirection.x != 0 && moveDirection.y != 0)
{
//为动画集赋值
//状态集的切换由运动矢量决定
anim.SetFloat("move X", lookDirection.x);
anim.SetFloat("move Y", lookDirection.y);
anim.SetFloat("runspeed", moveDirection.magnitude);
Debug.Log(lookDirection);
}
完整脚本,挂载即可使用
using UnityEngine;
using System.Collections;
public class Follow : MonoBehaviour
{
//目的地,射线与平面的交点
private Vector2 hitPoint;
//自动导航速度
public float speed = 3;
//是否点击
private bool clicked = false;
//定义动画
Animator anim;
//初始屏幕看
Vector2 lookDirection = new Vector2(0, -1);
// Use this for initialization
void Start()
{
//获取动画组件
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//方向向量
Vector2 curposition = new Vector2(gameObject.transform.position.x, gameObject.transform.position.y);
Vector2 moveDirection = hitPoint - curposition;
if (moveDirection.x != 0 || moveDirection.y != 0)
{
lookDirection = moveDirection;
}
//按下鼠标左键
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit2D raycast = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (raycast.collider != null)
{
hitPoint = new Vector2(raycast.point.x, raycast.point.y);
Debug.Log(raycast.point.x+"/"+ raycast.point.y);
Debug.Log("clicked object name is ---->" + raycast.collider.gameObject);
}
clicked = true;
}
//标记了才会自动导航
if (clicked) gameObject.transform.position = Vector2.MoveTowards(gameObject.transform.position, hitPoint, Time.deltaTime * speed);
//如果到达、则停止这次自动导航,取消标记
if (gameObject.transform.position.x== hitPoint.x && gameObject.transform.position.y== hitPoint.y)
{
clicked = false;
//默认停止显示正面或反面
anim.SetFloat("move X", 0);
anim.SetFloat("move Y", lookDirection.y);
anim.SetFloat("runspeed", 0);
Debug.Log(lookDirection);
}
//如果在自动前往目的地时,按下了方向键,撤销这次自动导航,取消标记
if(Input.GetAxisRaw("Horizontal")!=0||Input.GetAxisRaw("Vertical")!=0)
{
clicked = false;
}
//如果这次自动导航未被打断,并且未结束,标记仍然存在,则为运动中的动画状态集赋值,结束后回到运动前的朝向
if (clicked == true && moveDirection.x != 0 && moveDirection.y != 0)
{
//为动画集赋值
//状态集的切换由运动矢量决定
anim.SetFloat("move X", lookDirection.x);
anim.SetFloat("move Y", lookDirection.y);
anim.SetFloat("runspeed", moveDirection.magnitude);
Debug.Log(lookDirection);
}
}
}
鼠标导航状态的判断
到达目的地、则结束这次自动导航,并正确显示结束动画(停止后人物朝向与运动一致)
在到达前按下了方向键,撤销这次自动导航
到达前,并且未撤销导航,为动画状态集赋值,正确显示导航过程中的动画(运动中人物朝向与运动一致)
注意:该脚本必须配合以下代码使用,不然会有极其不良好的体验。
点击按键的时候,必须要取消自动导航,不然影响操作。
代码如下,放在按钮的函数里即可
//取消点击按钮造成的不必要移动
Follow.autonavi = false;
附完整教程: