最近要在VR里面制作一个射击的功能,枪是外接设备也不知道有没有后坐力,模拟一个先以防万一
这个是PC测试的,模拟的不是很真实,用摄像机的抖动造成后坐力的感觉,但是改改还是够用
首先是枪的发射脚本:
using UnityEngine;
public class GunRecoil : MonoBehaviour
{
private GameObject bullet;//子弹
private Vector3 FrontStar;//准星
private CameraController cam;//摄像机控制脚本
private float shootRate = 0.15f;//射击频率
private float shootTimer;//射击计时
private void Start()
{
bullet = transform.Find("Bullet").gameObject;
cam = Camera.main.GetComponent<CameraController>(); ;
LookAtStar();
}
private void Update()
{
if (Input.GetButton("Fire1"))
{
Fire();
}
else
{
if (Input.GetAxis("Mouse X") == 0 && Input.GetAxis("Mouse Y") == 0)
cam.Recover();
}
}
/// <summary>
/// 射击,射击频率,后坐力模拟
/// </summary>
private void Fire()
{
shootTimer += Time.deltaTime;
if (shootTimer >= shootRate)
{
GameObject go = Instantiate(bullet, bullet.transform.position, Quaternion.identity);
go.SetActive(true);
go.GetComponent<Rigidbody>().velocity = transform.forward * 20000;
Destroy(go, 4f);
shootTimer = 0;
cam.SimulateRecoil();
}
}
/// <summary>
/// 枪始终看向准星
/// </summary>
private void LookAtStar()
{
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
FrontStar = hit.point;
}
else
{
//Debug.DrawRay(Camera.main.transform.position,Camera.main.transform.forward * 1000,Color.red);
FrontStar = Camera.main.transform.forward * 1000;
}
transform.LookAt(FrontStar);
}
}
配置的结构:
脚本已经注释很清楚了,下面是摄像机的脚本,主要是一个旋转功能,抖动功能和恢复初始选择的功能:
using UnityEngine;
using UnityEngine.EventSystems;
public class CameraController : MonoBehaviour
{
public float RotateAngle;
public void CameraRotate()
{
float x_axis = Input.GetAxis("Mouse X");
float y_axis = Input.GetAxis("Mouse Y");
if (Input.GetMouseButton(1))
{
if (Mathf.Abs(x_axis) > Mathf.Abs(y_axis))
{
transform.Rotate(Vector3.up, RotateAngle * x_axis * Time.deltaTime);
}
if (Mathf.Abs(y_axis) > Mathf.Abs(x_axis))
{
if (transform.eulerAngles.x > -80 && transform.eulerAngles.x < 360)
{
transform.Rotate(Vector3.left, RotateAngle * y_axis * Time.deltaTime);
}
else
{
return;
}
}
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, 0);
if(!Input.GetButton("Fire1"))//如果不是在射击时移动镜头就设置最终旋转等于移动的旋转
lastQ = transform.rotation; //避免在射击时压枪射击完后镜头不恢复到射击前的状态
}
}
public float Max_X_Recoil;//X轴最大旋转偏移
public float Max_Y_Recoil;//Y轴最大旋转便宜
private float x_Range;//X轴射击时的旋转度
private float y_Range;//Y轴射击时的旋转度
public void SimulateRecoil()
{
x_Range = Random.Range(0.1f, Max_X_Recoil);
y_Range = Random.Range(0.1f, Max_Y_Recoil);
//transform.eulerAngles += transform.rotation * transform.up*x_Range+transform.rotation*transform.right * y_Range;//使用右乘会导致左右旋转后出现偏差
transform.eulerAngles = new Vector3(transform.eulerAngles.x-x_Range, transform.eulerAngles.y+y_Range, 0);//射击时的旋转
}
private Quaternion lastQ;//摄像机射击之前的旋转
public void Recover()
{
transform.rotation = Quaternion.Lerp(transform.rotation, lastQ, 5f * Time.deltaTime);//恢复之前的旋转
}
}
看下效果:
欢迎加群:4364930讨论