最近要在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讨论