无论是愤怒的小鸟,还是弓箭发射功能,亦或者模拟炮弹受重力影响等抛物线轨迹,都可以使用本文的方法,和往常一样,先说原理。就是抛物运动,在垂直方向上做加速度运动,在水平方向上,做匀速运动。
那么如何使用transform模拟呢?让物体同时在两个方向产生位移就行了,一个是初速度方向,一个是垂直方向。
垂直方向的速度 = a*t,a代表重力加速度,t代表已经运行的时间。
案例一、愤怒的小鸟
using UnityEngine;
using System.Collections;
public class newDus : MonoBehaviour {
public float Power = 10;//这个代表发射时的速度/力度等,可以通过此来模拟不同的力大小
public float Angle = 45;//发射的角度,这个就不用解释了吧
public float Gravity = -10;//这个代表重力加速度
private Vector3 MoveSpeed;//初速度向量
private Vector3 GritySpeed = Vector3.zero;//重力的速度向量,t时为0
private float dTime;//已经过去的时间
private Vector3 currentAngle;
// Use this for initialization
void Start()
{
//通过一个公式计算出初速度向量
//角度*力度
MoveSpeed = Quaternion.Euler(new Vector3(0, 0, Angle)) * Vector3.right * Power;
currentAngle = Vector3.zero;
}
// Update is called once per frame
void FixedUpdate()
{
//计算物体的重力速度
//v = at ;
GritySpeed.y = Gravity * (dTime += Time.fixedDeltaTime);
//位移模拟轨迹
transform.position += (MoveSpeed + GritySpeed) * Time.fixedDeltaTime;
currentAngle.z = Mathf.Atan((MoveSpeed.y + GritySpeed.y) / MoveSpeed.x) * Mathf.Rad2Deg;
transform.eulerAngles = currentAngle;
}
}
案例二、弓箭发射
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletFly : MonoBehaviour
{
public TrailRenderer trail;
public float speed = 20.0f;
public float curveHeightRate = 1.4f;
Vector3 startPos;
Vector3 endPos;
Vector3 ctrlPos;
float lifeTime; // 运行时间
float timeElapsed;
Transform trf;
Vector3 prevPos;
bool alive;
/// <summary> 发射 </summary>
public void Launch(Vector3 endPos)
{
alive = true;
startPos = trf.position;
this.endPos = endPos;
timeElapsed = 0.0f;
float dist = Vector3.Distance(endPos, startPos);
if (dist < 0.0000000001f)
{
dist = 0.0001f;
}
lifeTime = dist / speed;
Vector3 startPos_ = startPos;
startPos_.y = 0.0f;
Vector3 endPos_ = endPos;
endPos_.y = 0.0f;
ctrlPos = startPos_ + (endPos_ - startPos_) * 0.32f;
ctrlPos.y = dist * curveHeightRate;
float p = 0.01f;
Vector3 nextPos = (1.0f - p) * (1.0f - p) * startPos + 2 * p * (1.0f - p) * ctrlPos + p * p * endPos;
Vector3 rotate = nextPos - startPos;
trf.rotation = Quaternion.LookRotation(rotate);
prevPos = startPos;
trail.Clear();
}
void Awake()
{
trf = transform;
}
void Update()
{
if (!alive)
return;
timeElapsed += Time.deltaTime;
float p = timeElapsed / lifeTime;
if (p > 1.0f)
{
p = 1.0f;
}
Vector3 pos = (1.0f - p) * (1.0f - p) * startPos + 2 * p * (1.0f - p) * ctrlPos + p * p * endPos;
trf.position = pos;
Vector3 rotate = pos - prevPos;
trf.rotation = Quaternion.LookRotation(rotate);
prevPos = pos;
if (p >= 1.0f)
{
KillSelf();
}
}
void KillSelf()
{
if (!alive)
return;
alive = false;
gameObject.SetActive(false);
BulletPool.Instance.AddArrowBullet(this);
}
}
//使用
BulletFly arrow = BulletPool.Instance.GetArrowBullet();
arrow.transform.position = transform.position;
arrow.Launch(target.position);
arrow.gameObject.SetActive(true);