前言
經過三個小時研究,終於實現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;
附完整教程: