之前的斜抛运动,如果运动到游戏中,显然是太呆板了,那么可以试着加入一些效果,让它看起来更生动一些,类似游戏中的击飞或者掉落效果:
1.在达到最高点的时间点±X的时间段内,会有“减速”效果,形成一种在空中停留的感觉
2.落地后,反弹一次,再落地,就像是与地面发生了碰撞
相关公式:
ObliqueThrow.cs
1 using System; 2 using UnityEngine; 3 4 public class ObliqueThrow : MonoBehaviour { 5 6 private float gravity; //重力加速度(当前) 7 private float gravityValue = -9.8f; //重力加速度值1 8 private Vector2 horizontalDir; //水平方向 9 private float startSpeed; //初速度 10 private float sinValue; //sin值 11 private float cosValue; //cos值 12 private Vector3 startPos; //开始位置 13 private float endY; //结束高度(地面高度) 14 private float timer; //运动消耗时间 15 private Action<GameObject> finishCallBack; //落地后的回调 16 private bool canMove = false; //能否运动 17 18 private float timeScale = 1; //时间系数 19 private float reboundTimes = 1; //反弹次数 20 private bool isInRebound = false; //是否在反弹中 21 private float lastX; //落地点x 22 private float lastZ; //落地点z 23 private float hightestPointTime; //到达最高点所用的时间 24 private float hightestPointStayTime = 0.1f; //最高点减速范围的时间段 25 26 void Update() 27 { 28 if (!canMove) 29 { 30 return; 31 } 32 33 //移动过程 34 timer = timer + Time.deltaTime * timeScale; 35 36 float xOffset = startSpeed * timer * cosValue * horizontalDir.x; 37 float zOffset = startSpeed * timer * cosValue * horizontalDir.y; 38 float yOffset = startSpeed * timer * sinValue + 0.5f * gravity * timer * timer; 39 40 Vector3 endPos; 41 if (!isInRebound) //非反弹过程 42 { 43 endPos = startPos + new Vector3(xOffset, yOffset, zOffset); 44 if (Mathf.Abs(timer - hightestPointTime) < hightestPointStayTime) 45 { 46 timeScale = 0.5f; 47 } 48 else 49 { 50 timeScale = 1f; 51 } 52 } 53 else //反弹过程 54 { 55 endPos = new Vector3(lastX, yOffset, lastZ); 56 } 57 58 //落地 59 if (endPos.y < endY) 60 { 61 endPos.y = endY; 62 63 reboundTimes = reboundTimes - 1; 64 if (reboundTimes < 0) //移动结束 65 { 66 canMove = false; 67 } 68 else //落地反弹 69 { 70 gravity = gravityValue * 2; 71 horizontalDir = Vector2.zero; 72 startSpeed = startSpeed * 0.8f; 73 sinValue = 1; 74 cosValue = 0; 75 timer = 0; 76 77 isInRebound = true; 78 lastX = endPos.x; 79 lastZ = endPos.z; 80 } 81 } 82 transform.position = endPos; 83 84 //移动结束 85 if (!canMove) 86 { 87 finishCallBack(gameObject); 88 Destroy(this); 89 } 90 } 91 92 public void StartMove(Vector2 horizontalDir, float startSpeed, float angle, float endY, Action<GameObject> finishCallBack) 93 { 94 gravity = gravityValue; 95 this.horizontalDir = horizontalDir; 96 this.startSpeed = startSpeed; 97 sinValue = Mathf.Sin(Mathf.Deg2Rad * angle); 98 cosValue = Mathf.Cos(Mathf.Deg2Rad * angle); 99 startPos = transform.position; 100 this.endY = endY; 101 timer = 0; 102 this.finishCallBack = finishCallBack; 103 canMove = true; 104 105 hightestPointTime = Mathf.Abs(startSpeed * sinValue / gravity); 106 } 107 }
TestThrow.cs
1 using UnityEngine; 2 using System.Collections.Generic; 3 4 public class TestThrow : MonoBehaviour { 5 6 public GameObject testGo; 7 private bool isDebug = false; 8 private List<GameObject> drawGoList = new List<GameObject>(); 9 10 void Update () 11 { 12 if (Input.GetKeyDown(KeyCode.Q)) 13 { 14 //半径为1的方向圆 15 float randomNum = Random.Range(0f, 1f);//[0, 1] 16 float x = randomNum * 2 - 1;//[-1, 1] 17 float z = Mathf.Sqrt(1 - x * x); 18 if (Random.Range(0f, 1f) > 0.5f) 19 { 20 z = -z; 21 } 22 23 isDebug = true; 24 ObliqueThrow obliqueThrow = testGo.AddComponent<ObliqueThrow>(); 25 obliqueThrow.StartMove(new Vector2(1, 0), 5f, 45f, 0f, (go) => { 26 isDebug = false; 27 Debug.Log("移动结束"); 28 }); 29 } 30 else if(Input.GetKeyDown(KeyCode.W)) 31 { 32 testGo.transform.position = new Vector3(0f, 5f, 0f); 33 for (int i = 0; i < drawGoList.Count; i++) 34 { 35 Destroy(drawGoList[i]); 36 } 37 drawGoList.Clear(); 38 } 39 40 if (isDebug) 41 { 42 GameObject go = GameObject.CreatePrimitive(PrimitiveType.Sphere); 43 go.transform.position = testGo.transform.position; 44 go.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); 45 drawGoList.Add(go); 46 } 47 } 48 }
效果如下: