在物理世界中,让子弹的刚体受到一个冲量,就可以简单的实现子弹的飞行。
Body.AddForce(Direction * Froce , ForceMode.Impulse);
而ForceMode.Impulse:此种方式采用瞬间力作用方式,即把t的值默认为1,不再采用系统的帧频间隔,即
f•1.0=m•v
那么v=f/m
如果射击的物体是移动的,那刚体的初速度则为射击物体的速度。
故v=v0+f/m
最近遇到一个需求,已知初速度和冲量,要绘制出子弹的轨迹。
如下图效果:
考虑把它分成x轴和y轴的运动。
即,在x轴上匀速运行,在y轴方向上加速运动。
using UnityEngine; using System.Collections; using System.Collections.Generic; public class DrawBulletPath : MonoBehaviour { //用于显示的点 public GameObject point; //最初冲量 [HideInInspector] public Vector3 Forces; //点的数量 public int PointCount = 60; //绘制点的时间间距 public float Interval = 0.02f; //是否可以绘制 private bool _drawEnabled; private List<GameObject> pointList = new List<GameObject>(); //显示点的数量(由于与地形碰撞,所以有些点不显示) public int ShowCount = 0; //子弹的重量 public float Mass = 1.0f; public bool DrawEnabled { get { return _drawEnabled; } set { if(value != _drawEnabled) { if (!value) Clean(); else ShowCount = PointCount; } _drawEnabled = value; } } void Start() { transform.DestroyChildren(); for (int i = 0; i < PointCount; i++) { var go = Instantiate(point) as GameObject; go.transform.parent = transform; var pathPoint = go.GetComponent<PathPoint>(); pathPoint.ResetState(); pathPoint.Index = i; pathPoint.dbp = this; pointList.Add(go); } DrawEnabled = false; ShowCount = PointCount; } //绘制路径 void CreateLine() { float t = 0.0f; for (int i = 0; i < PointCount; i++) { var go = pointList[i]; float posx = Forces.x / Mass * t; float posy = Forces.y * t / Mass + Physics.gravity.y * t * t / 2; go.transform.localPosition = new Vector3(posx, posy, 0); var pathPoint = go.GetComponent<PathPoint>(); if (i < ShowCount) pathPoint.Show(); else pathPoint.Hide(); t += Interval; } } void Awake() { BattleFieldManager.GetInstance().DBP = this; } public void Update() { if (!_drawEnabled) return; if (Forces != Vector3.zero) { CreateLine(); CheckCollider(); } } List<int> ColliderList = new List<int>(); void CheckCollider() { for (int i = 0; i < PointCount; i++) { var point = pointList[i].GetComponent<PathPoint>(); if (point.ColliderTerrian) ColliderList.Add(i); } //用于淘汰掉与地形碰撞的 if (ColliderList.Count > 0) { ColliderList.Sort(); ShowCount = ColliderList[0]; ColliderList.Clear(); } } public void Clean() { for (int i = 0; i < PointCount; i++) { pointList[i].GetComponent<PathPoint>().ResetState(); } } }