问题描述
我正在使用子弹制作第一人称射击游戏,我正在尝试找到一种方法来删除击中敌人或墙壁但无法正常工作的实例。我这样做的方法是给所有的墙壁和敌人一个标签,用于特定的碰撞检测,但它似乎不起作用 对我来说。
请帮忙
using UnityEngine;
using TMPro;
public class BulletShoot : MonoBehavIoUr
{
//bullet
public GameObject bullet;
//bullet force
public float shootForce,upwardForce;
//Gun stats
public float timeBetweenShooting,spread,reloadTime,timeBetweenShots;
public int magazinesize,bulletsPerTap;
public bool allowButtonHold;
int bulletsLeft,bulletsShot;
//Recoil
public Rigidbody playerRb;
public float recoilForce;
//bools
bool shooting,readyToShoot,reloading;
//Reference
public Camera fpsCam;
public Transform attackPoint;
//Graphics
public GameObject muzzleFlash;
public TextMeshProUGUI ammunitiondisplay;
//bug fixing :D
public bool allowInvoke = true;
private void Awake()
{
//make sure magazine is full
bulletsLeft = magazinesize;
readyToShoot = true;
}
private void Update()
{
Myinput();
//Set ammo display,if it exists :D
//if (ammunitiondisplay != null)
//ammunitiondisplay.SetText(bulletsLeft / bulletsPerTap + " / " + magazinesize / bulletsPerTap);
}
private void Myinput()
{
//Check if allowed to hold down button and take corresponding input
if (allowButtonHold) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
//Reloading
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazinesize && !reloading) Reload();
//Reload automatically when trying to shoot without ammo
if (readyToShoot && shooting && !reloading && bulletsLeft <= 0) Reload();
//Shooting
if (readyToShoot && shooting && !reloading && bulletsLeft > 0)
{
//Set bullets shot to 0
bulletsShot = 0;
Shoot();
}
}
private void Shoot()
{
readyToShoot = false;
//Find the exact hit position using a raycast
Ray ray = fpsCam.ViewportPointToRay(new Vector3(0.5f,0.5f,0)); //Just a ray through the middle of your current view
RaycastHit hit;
//check if ray hits something
Vector3 targetPoint;
if (Physics.Raycast(ray,out hit))
targetPoint = hit.point;
else
targetPoint = ray.GetPoint(75); //Just a point far away from the player
//Calculate direction from attackPoint to targetPoint
Vector3 directionWithoutSpread = targetPoint - attackPoint.position;
//Calculate spread
float x = Random.Range(-spread,spread);
float y = Random.Range(-spread,spread);
//Calculate new direction with spread
Vector3 directionWithSpread = directionWithoutSpread + new Vector3(x,y,0); //Just add spread to last direction
//Instantiate bullet/projectile
GameObject currentBullet = Instantiate(bullet,attackPoint.position,Quaternion.identity); //store instantiated bullet in currentBullet
//Rotate bullet to shoot direction
currentBullet.transform.forward = directionWithSpread.normalized;
//Add forces to bullet
currentBullet.GetComponent<Rigidbody>().AddForce(directionWithSpread.normalized * shootForce,ForceMode.Impulse);
currentBullet.GetComponent<Rigidbody>().AddForce(fpsCam.transform.up * upwardForce,ForceMode.Impulse);
if(currentBullet.gameObject.CompareTag("Enemy"))
{
Destroy(currentBullet.gameObject,3);
}
if (currentBullet.gameObject.CompareTag("Thing"))
{
Destroy(currentBullet.gameObject,3);
}
//Instantiate muzzle flash,if you have one
if (muzzleFlash != null)
Instantiate(muzzleFlash,Quaternion.identity);
bulletsLeft--;
bulletsShot++;
//Invoke resetShot function (if not already invoked),with your timeBetweenShooting
if (allowInvoke)
{
Invoke("ResetShot",timeBetweenShooting);
allowInvoke = false;
//Add recoil to player (should only be called once)
playerRb.AddForce(-directionWithSpread.normalized * recoilForce,ForceMode.Impulse);
}
//if more than one bulletsPerTap make sure to repeat shoot function
if (bulletsShot < bulletsPerTap && bulletsLeft > 0)
Invoke("Shoot",timeBetweenShots);
}
private void ResetShot()
{
//Allow shooting and invoking again
readyToShoot = true;
allowInvoke = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished",reloadTime); //Invoke ReloadFinished function with your reloadTime as delay
}
private void ReloadFinished()
{
//Fill magazine
bulletsLeft = magazinesize;
reloading = false;
}
}
解决方法
我有两件事要说。
首先,如果您使用光线投射来查找您击中的位置,那么使用子弹对象似乎有点不必要,但如果您想这样做也没关系。
第二个是子弹对象不是即时的,所以当你在 Shoot() 中给子弹加力时,子弹仍然没有移动。然后您检查它是否与同一帧上的任何东西发生碰撞,也在 Shoot() 中,这仍然意味着子弹尚未移动。我建议将碰撞检测从 Shoot() 方法中移到一个单独的方法中,然后我将在 update() 中调用该方法,与 Input() 分开。
希望这有帮助 :D