在玩捕魚遊戲時候看到金币獲得移動表現,那麼作為一個程式員就會想這個表現是怎麼實作,如果我來弄又是怎麼方法!在這裡我将自己的實作和想法寫下來。
經過觀察和發現,漁場金币表現分為:先将N個金币爆炸開,在回收,最後進行移動到目标位置。
具體邏輯看下面代碼:
抛物線下運動代碼
using UnityEngine;
public class ParabolaPath
{
public bool isClampStartEnd;
private Vector3 m_start;
private Vector3 m_end;
private float m_height;
private float m_gravity;
private float m_upTime;
private float m_downTime;
private float m_totalTime;
private Vector3 m_velocityStart;
private Vector3 m_position;
private float m_time;
/// <summary> 初始化 </summary>
/// <param name="start">開始點</param>
/// <param name="end">結束點</param>
/// <param name="height">高度</param>
/// <param name="gravity">重力加速度</param>
/// <returns></returns>
public void Init(Vector3 start, Vector3 end, float height = 10, float gravity = -9.8f)
{
float topY = Mathf.Max(start.y, end.y) + height;
float d1 = topY - start.y;
float d2 = topY - end.y;
float g2 = 2 / -gravity;
float t1 = Mathf.Sqrt(g2 * d1);
float t2 = Mathf.Sqrt(g2 * d2);
float t = t1 + t2;
float vX = (end.x - start.x) / t;
float vZ = (end.z - start.z) / t;
float vY = -gravity * t1;
m_start = start;
m_end = end;
m_height = height;
m_gravity = gravity;
m_upTime = t1;
m_downTime = t2;
m_totalTime = t;
m_velocityStart = new Vector3(vX, vY, vZ);
m_position = m_start;
m_time = 0;
}
/// <summary> 起點 </summary>
public Vector3 start { get { return m_start; } }
/// <summary> 終點 </summary>
public Vector3 end { get { return m_end; } }
/// <summary> 目标高度 </summary>
public float height { get { return m_height; } }
/// <summary> 重力加速度 </summary>
public float gravity { get { return m_gravity; } }
/// <summary> 上升時間 </summary>
public float upTime { get { return m_upTime; } }
/// <summary> 下降時間 </summary>
public float downTime { get { return m_downTime; } }
/// <summary> 總運動時間 </summary>
public float totalTime { get { return m_totalTime; } }
/// <summary> 頂點 </summary>
public Vector3 top { get { return GetPosition(m_upTime); } }
/// <summary> 初始速度 </summary>
public Vector3 velocityStart { get { return m_velocityStart; } }
/// <summary> 目前位置 </summary>
public Vector3 position { get { return m_position; } }
/// <summary> 目前速度 </summary>
public Vector3 velocity { get { return GetVelocity(m_time); } }
/// <summary> 目前時間 </summary>
public float time
{
get { return m_time; }
set
{
if (isClampStartEnd) value = Mathf.Clamp(value, 0, m_totalTime);
m_time = value;
m_position = GetPosition(value);
}
}
/// <summary> 擷取某個時間點的位置 </summary>
public Vector3 GetPosition(float time)
{
if (time == 0) return m_start;
if (time == m_totalTime) return m_end;
float dY = 0.5f * m_gravity * time * time;
return m_start + m_velocityStart * time + new Vector3(0, dY, 0);
}
/// <summary> 擷取某個時間點的速度</summary>
public Vector3 GetVelocity(float time)
{
if (time == 0) return m_velocityStart;
return m_velocityStart + new Vector3(0, m_velocityStart.y + m_gravity * time, 0);
}
}
曲線運動方法 對DG.Tweening的運用
using DG.Tweening;
using UnityEngine;
public class MoveItme : MonoBehaviour
{
//移動持續時間
private float m_MoveTime = 2.0f;
//加速移動倍數
private float m_MoveRate = 2.0f;
//開始位置
private Vector3 m_StartPos = Vector3.zero;
//目标位置
private Vector3 m_TargetPos = Vector3.zero;
//移動方式
private Ease m_Ease;
/// <summary>
/// 設定移動
/// </summary>
/// <param name="movetime">移動持續時間</param>
/// <param name="moverate">加速移動倍數</param>
/// <param name="ease">移動方式 : Ease.Linear </param>
/// <param name="startpos">開始位置</param>
/// <param name="targetpos">目标位置</param>
/// <param name="callback">回調</param>
public void SetMove(float movetime, float moverate, int ease, Vector3 startpos, Vector3 targetpos, System.Action callback)
{
m_MoveTime = movetime;
m_MoveRate = moverate;
m_Ease = (Ease)ease;
m_StartPos = startpos;
m_TargetPos = targetpos;
MoveLocal(callback);
}
void MoveLocal(System.Action callback)
{
transform.localPosition = m_StartPos;
Tweener m_Tweener = transform.DOLocalMove(m_TargetPos, m_MoveTime);
if (m_Tweener != null)
{
m_Tweener.timeScale = m_MoveRate;
m_Tweener.SetEase(m_Ease);
m_Tweener.OnComplete(() =>
{
if (callback != null)
{
callback();
}
});
}
}
}
----------------------------------------------
以下是對上面的方法調用邏輯
using System;
using UnityEngine;
public class ParabolaPathUtils : MonoBehaviour
{
public Vector3 target; // 目标
public float height = 16f; // 高度
public float gravity = -1000.0f; // 重力加速度
private ParabolaPath path; // 抛物線運動軌迹
private bool isplay = false;
public Action callback;
public void SetStart()
{
path = new ParabolaPath();
path.Init(transform.localPosition, target, height, gravity);
path.isClampStartEnd = true;
isplay = true;
}
private void Update()
{
if (!isplay)
{
return;
}
// 計算位移
float t = Time.deltaTime;
path.time += t;
transform.localPosition = path.position;
// 計算轉向
//transform.LookAt(path.GetPosition(path.time + t));
// 簡單模拟一下碰撞檢測
if (path.time >= path.totalTime)
{
isplay = false;
if (callback != null)
{
callback();
}
}
}
}
調用表現
using System.Collections;
using UnityEngine;
public class MoveTest : MonoBehaviour
{
public GameObject obj;
public GameObject _ObjStartVec3;
public GameObject _ObjEndVec3;
public float movetime = 1.0f;
public float moverate = 5.0f;
public Vector2 RandomVec = Vector2.zero;
public int ease = 1;
public float gravity = -2000;
public float height = 20;
Vector3 StartVec3;
Vector3 EndVec3;
void Start()
{
StartVec3 = _ObjStartVec3.transform.localPosition;
EndVec3 = _ObjEndVec3.transform.localPosition;
for (int i=0;i<10;i++)
{
InitModel(i);
}
}
void InitModel(int index)
{
GameObject _obj = Instantiate(obj) as GameObject;
if(_obj==null)
{
return;
}
_obj.transform.parent = this.gameObject.transform;
_obj.transform.localPosition = StartVec3;
Vector2 Vec = Random.insideUnitCircle;
Vector3 Pos = StartVec3 + (new Vector3(Vec.x * RandomVec.x, Vec.y * RandomVec.y));
MoveItme mMoveItme = _obj.transform.GetComponent<MoveItme>();
if(mMoveItme==null)
{
mMoveItme = _obj.gameObject.AddComponent<MoveItme>();
}
mMoveItme.SetMove(movetime, moverate, ease, StartVec3, Pos, () => {
StartCoroutine(OnWait(index, mMoveItme, Pos));
});
}
IEnumerator OnWait(int index, MoveItme mMoveItme,Vector3 Pos)
{
yield return new WaitForSeconds(index + 0.5f);
mMoveItme.SetMove(movetime, moverate, ease, Pos, StartVec3,() => {
ParabolaPathUtils mParabolaPathUtils = mMoveItme.transform.GetComponent<ParabolaPathUtils>();
if (mParabolaPathUtils == null)
{
mParabolaPathUtils = mMoveItme.gameObject.AddComponent<ParabolaPathUtils>();
}
mParabolaPathUtils.callback = mCallBack;
mParabolaPathUtils.gravity = gravity;
mParabolaPathUtils.height = height;
mParabolaPathUtils.target = EndVec3;
mParabolaPathUtils.SetStart();
});
}
void mCallBack()
{
Debug.Log("--mCallBack--");
}
}
具體的看執行個體工程
--------------
資源稽核中,完後補充資源連結
https://download.csdn.net/download/sun__ch/12319933