日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Unity】用Lerp()实现类杀戮尖塔手牌变化

發布時間:2024/1/8 编程问答 102 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Unity】用Lerp()实现类杀戮尖塔手牌变化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Lerp的種類

  • math類里的Lerp函數可以對很多種數據類型進行插值,這里主要用的是Vector3的,因為變換position、scale都要用
  • 這里的難點是rotation,我試了用Quaternion.Lerp但是放棄了,因為參數必須也是Quaternion類型的(注意大寫),
`public static Quaternion Lerp(Quaternion a, Quaternion b, float t);`

所以transform.rotation是不能作為參數的,quaternion.Eular(transform.eularangle)轉換成的歐拉角同樣也是用不了的,所以只能從歐拉角或借助LookRotation函數里加Lerp來變換

Hover時手牌強調動畫

  • 強調分三部分:放大、向上移動、取消原有的旋轉,既然是Lerp做平滑,就一定是在update里,但是獲取鼠標懸浮事件又需要OnMouseEnter,我的解決方法是用bool類型控制update中Lerp的開啟或關閉
//鼠標進入if (zoomIn && !zoomOut){Focus();}//鼠標退出if (zoomOut && !zoomIn){UnFocus();}
  • 放大和向上移動很簡單,注意transform.position就已經是世界坐標了,OnMouseExit的動畫其實也就是lerp的一二兩個參數對調一下
lerpTime += Time.deltaTime * zoomSpeed;if (lerpTime <= 1){transform.localScale = math.lerp(originscale, originscale * scaleRate, lerpTime);transform.position = math.lerp(originPosition, originPosition + Vector3.up * moveDistance, lerpTime);transform.localRotation = quaternion.LookRotationSafe(Vector3.forward,math.lerp(Vector3.up,originEular,lerpTime)); //Debug.Log(transform.localEulerAngles);}
  • 注意旋轉值插值的lerp我放在了lookRotation里面,為什么不直接用歐拉角Lerp呢?畢竟它就是Vector3,理論上可以。因為Lerp對歐拉角的Lerp有坑,例如明明一開始歐拉角是(0,0,-15),要Lerp到(0,0,0),但是過程中會出現(0,0,200),查了半天也不知道怎么會有這種問題,所以最后用的是在(0,0,15)和(0,1,0)間的插值,插值的結果再進入lookRotation,實現卡牌被hover時擺正的效果
  • 在lookRotation的使用中,理解起來還挺抽象的,表示三維空間的朝向為什么要兩個三維向量呢?例如希望卡牌歐拉角為(0,0,0),正對攝像機,那么lookRotation就是(Vector3.forward,Vector3.up)。我的理解是,想象卡牌是個人,你想讓它看著你,那就是面對著你(forward),頭頂朝天(up),剛才我的旋轉插值本質上就是在卡牌頭頂正對天和斜對天進行插值
  • 比較容易被忽略的是,Lerp的插值插值其實并不能保證變換的程度完全是設置的程度,例如一次縮放結束后,可能和變換前有0.01的誤差,雖然它很小,但積累起來就麻煩了,那怎么辦呢?保險起見我在每次Lerp的最后加了一個直接變換
transform.localScale = originscale;transform.position = originPosition;

動態生成數量不同的手牌

基礎位置也就是手牌區正中間我已經定好了,在此基礎上計算每張卡的xy相對位移

private Vector3 CalTargetPos(int cardIndex,int cardTotal){//發的手牌數為奇數if(cardTotal % 2 == 1){var xPos = Vector3.left * (math.ceil(cardTotal / 2)) + Vector3.right * cardIndex;var yPos = Vector3.down * math.abs(math.ceil(cardTotal / 2) - cardIndex);return transform.position + CardXSpace * (xPos) + CardYSpace * (yPos);}//為偶數else{var xPos = Vector3.left * ((cardTotal / 2) - 0.5f) + Vector3.right * cardIndex;var yPos = Vector3.down * math.abs(cardTotal / 2 - cardIndex - 0.5f);return transform.position + CardXSpace * (xPos) + CardYSpace * (yPos);}private quaternion CalTargetQua(int cardIndex,int cardTotal){//發的手牌數為奇數if (System.DelivercardNum % 2 == 1){ return quaternion.LookRotation(Vector3.forward,Vector3.up + CardEular * Vector3.right * (cardIndex - math.ceil(cardTotal / 2)));}//為偶數else{return quaternion.LookRotation(Vector3.forward, Vector3.up + CardEular * Vector3.right * (cardIndex - ((cardTotal / 2) - 0.5f))); ;}}}
  • 每局發牌的數量多少和奇偶性都會對卡牌位置的計算產生影響,如果是奇數,那就一張卡在中間,旁邊的依次排開,如果是偶數,就是對稱分布,所以要先判斷此局發牌數的奇偶性
  • 公式比較好理解,就不細講了
  • 注意旋轉的函數,雖然這里可以用rotate,但是為了避免四元數和歐拉角轉換過程中可能的問題,還是用LookRotation

手牌數量減少后的重新布局

本質上還是運用上述的計算公式,在有卡牌被銷毀時重新計算,但是難點在于,在原有的腳本調用順序中,無論如何也只能在卡牌被銷毀之前獲取消息,那么此時關卡中的卡牌總數還未變化(因為還未銷毀),所以計算的結果沒變化,我的解決方案就是

  • 把將刪除的卡的tag改了
  • 按tag查找不會被銷毀的卡、
  • 如果還有卡
  • 調用重計算位置的方法
  • 否則不調用

當卡牌的運動狀態過多時用枚舉類型避免混亂

現在卡牌已經有了好幾種行為了:放大、縮小、發牌時移動、重布局時移動……,為了避免卡牌移動時被hover可能產生的問題,需要在lerp之前加入判斷,但是都設置個bool值就太麻煩了,這時候就需要枚舉類型,我是在brackey的類寶可夢回合制教程里學會的,這是B站視頻鏈接
最后在Updete里用switch判斷狀態,再調用封裝好的函數,比用bool清晰整潔多了

public enum BattleCardState { zoomIn, zoomOut, returning, dragging, move, settle } void Update(){if (!GameObject.FindGameObjectWithTag("CardView")){switch (cardState){//拖拽狀態case BattleCardState.dragging :{Vector3 mousePos = MouseInWorldCoords();da.OnDraggingInUpdate();break;}//松開后返回狀態case (BattleCardState.returning):{LerpToOrigin();break;}//放大狀態case (BattleCardState.zoomIn):{Focus();break;}//縮小狀態case (BattleCardState.zoomOut):{UnFocus();break;}//移動狀態case (BattleCardState.move):{Debug.Log("move");transform.position = math.lerp(transform.position, originPosition, Time.deltaTime * 3);transform.localRotation = quaternion.LookRotationSafe(Vector3.forward, math.lerp(Vector3.up, originEular, Time.deltaTime * 3));if ((transform.position - originPosition).magnitude < 0.1f){cardState = BattleCardState.settle;transform.position = originPosition;transform.eulerAngles = originEular;}break;}}}}

總結

以上是生活随笔為你收集整理的【Unity】用Lerp()实现类杀戮尖塔手牌变化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。