【Unity3D基礎】讓物體動起來②--UGUI鼠標點擊逐幀移動


背景

上一篇通過鼠標移動的代碼很簡單,所以看的人也不多,但是還是要感謝“武裝三藏”在博客園給出的評論和支持,希望他也能看到第二篇,其實可以很簡單,而且是精靈自控制,關鍵是代碼少是我喜歡的方式,也再次印證了Unity3d的復雜性(同樣的功能多次封裝),代碼如下:

public class DebugTest : MonoBehaviour
{
RectTransform m_Rect;

void Start ()
{
m_Rect = GetComponent<RectTransform>();
}

void Update()
{
if(Input.GetMouseButtonUp(0))
{
m_Rect.position = Input.mousePosition;
}

}

}

  

效果如下(由於效果基本相似,接上一篇的預覽圖):

run

這一篇主要解決上一篇最后提出的問題,也就是通過這樣鼠標移動物體時不夠平滑的,不管有多遠都是瞬移過去的,視覺體驗不夠優秀。

本文旨在通過Update中逐幀移動。達到平滑移動的效果

原理

1、記錄鼠標點擊的點,這個點是如果是屏幕坐標
2、將這個屏幕坐標轉換成世界坐標
3、使用鼠標的世界坐標-精靈的世界坐標||也可以使用鼠標的本地坐標-精靈的本地坐標
4、通過3獲得移動方向,做插值在Update里面移動精靈
5、移動精靈可以使用世界坐標移動,也可以通過local本地坐標移動

實現1

通過UGUI 事件系統中的IPointerClickHandler實現鼠標點擊,然后在Update中逐幀移動,所有坐標使用LocalPosition,原理很簡單這里代碼不啰嗦

   private RectTransform childPlayTransform;
    private float speed =10.0f;
    private Vector2 pointClickPostion;
    private Vector3 currentLocalPostion;
    private Vector3 moveDirect;
    // Use this for initialization
    void Start ()
    {
       //獲得Image的Transform
        childPlayTransform = transform.Find("Image").GetComponent<RectTransform>();
       }
    
    // Update is called once per frame
    void Update ()
    {
            currentLocalPostion = childPlayTransform.localPosition;
            Vector3 targetPosition = moveDirect * speed + currentLocalPostion;
        childPlayTransform.localPosition = Vector3.Lerp(currentLocalPostion, targetPosition, Time.deltaTime*4f);
        }

    public void OnPointerClick(PointerEventData eventData)
    {
        Vector2 localPoint;
        //在矩形范圍內檢測,全局鼠標點擊點,到local點的轉換
        RectTransformUtility.ScreenPointToLocalPointInRectangle(transform.GetComponent<RectTransform>() , eventData.position,
            eventData.enterEventCamera, out localPoint);

        pointClickPostion = localPoint;

        moveDirect = new Vector3(pointClickPostion.x, pointClickPostion.y, 0) - currentLocalPostion;
        moveDirect.z = 0;
        moveDirect.Normalize();
    }

  

實現2

通過Unity3d 輸入系統Input輸入得鼠標位置,然后再Update中使用世界坐標進行精靈的逐幀平移,代碼如下:

private Transform spriteTransform;
  Vector3 direction;
  Vector3 spriteCurentPoistion;
  Vector3 targetPosition;
  float speed = 2.0f;
  void Start () {
      spriteTransform = transform.Find("Image") as Transform;
  }

  // Update is called once per frame
  void Update () {
      spriteCurentPoistion = spriteTransform.position;
      //向量加法(向鼠標方向)
      targetPosition = direction * speed + spriteCurentPoistion;

      spriteTransform.position = targetPosition;
  }

  public void OnPointerClick(PointerEventData eventData)
  {
      Vector3 mouseWorldPointer = new Vector3(eventData.position.x, eventData.position.y, 0);
      //屏幕坐標轉換成世界坐標
      //Vector3 mouseWorldPointer = Camera.main.ScreenToWorldPoint(mouseScreenPointer);
      //向量減法獲得指向鼠標點的方向
      direction = mouseWorldPointer - spriteTransform.position;
      direction.z = 0;
      direction.Normalize();
      Debug.Log(string.Format("x:{0},y:{1}-- {2},{3}", mouseWorldPointer.x, mouseWorldPointer.y, eventData.position.x, eventData.position.y));
  }

  

問題記錄

在試驗的時候遇到一些小問題,特此記錄,也希望高手路過慷慨回答

1、關於進行顯性插值函數

Vector3.Lerp(currentLocalPostion, targetPosition, Time.deltaTime*4f);

實際這是一個公式也很簡單,就是我看教程(Unity3d)的時候Time.deltaTime這個值很大,而實際中發現這個值很小,造成插值的時候很微量的移動,不知為何只能乘以一個系數

2、關於Unity3d的Input輸入的函數提示很弱

比如 eventData.position和Input.mousePosition到底是什么坐標是屏幕坐標還是世界坐標,文檔模棱兩可並沒有說明

總結

在實現一個如此小的功能,給人深刻影響的可以使用的方法很多,遇到一些知識點,原理也很簡單,但你不深入卻得不到答案。這個世界就像快餐,變得太快。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM