产生的子弹比允许的多
More bullets spawn than allowed
不确定为什么会发生这种情况,但此代码允许在重新加载后发射超过 3 发子弹。我想找出原因。我认为这可能是检查哪个问题之间的时间,但我可能是错的。
如有任何帮助,我们将不胜感激。
public bool isFiring;
public bool isReloading = false;
public BulletController bullet; // Reference another script
public float bulletSpeed; // bullet speed
public float timeBetweenShots; // time between shots can be fired
private float shotCounter;
public Transform firePoint;
public static int ammoRemaining = 3;
public static int maxAmmo = 3;
public Transform ammoText;
// Use this for initialization
void Awake () {
isReloading = false;
ammoRemaining = maxAmmo;
}
// Update is called once per frame
void Update () {
if(isFiring == true )
{
shotCounter -= Time.deltaTime;
if(shotCounter <= 0 && ammoRemaining > 0 && isReloading == false)
{
shotCounter = timeBetweenShots;
BulletController newBullet = Instantiate(bullet, firePoint.position, firePoint.rotation) as BulletController; // creates a new instance of the bullet
newBullet.speed = bulletSpeed;
ammoRemaining -= 1;
ammoText.GetComponent<Text>().text = "Ammo:" + ammoRemaining;
}
}
else if (ammoRemaining == 0)
{
StartCoroutine(Reload());
}
else
{
shotCounter = 0;
}
}
public IEnumerator Reload()
{
isReloading = true;
ammoText.GetComponent<Text>().text = "REL...";
yield return new WaitForSeconds(2);
ammoRemaining = maxAmmo;
isReloading = false;
ammoText.GetComponent<Text>().text = "Ammo:" + ammoRemaining;
}
问题(如讨论的那样)是在您发射最后一枪之后和放开 MouseButton(0) 之前,您的 Reload() 协程在 Update() 中被调用了额外的次数。为避免这种情况,我建议在启动协程之前检查以确保您尚未重新加载:
else if (ammoRemaining == 0 && !isReloading)
{
StartCoroutine(Reload());
}
这是一个题外话,不是为了解决你的问题,而是为了避免你以后出现问题,特别是性能方面的问题。如果您打算开发 3D 射击游戏,我建议您不要实例化子弹(除非您打算创建一些延时场景)
原因有二:
- 您将需要每秒实例化和销毁许多游戏对象
- 如果你给子弹一个逼真的速度,它不应该在
现场
我假设为您实例化子弹的原因主要是以下两个:
- 为了创造一些离开得非常快的视觉效果
按下射击时的枪管
- 检测您是否用
OnCollisionEnter()
或类似的 击中目标
所以我可以给你一些提示,你可以尝试一些东西而不是实例化项目符号。
1- 为了表示射击,您可以在枪管末端安装一盏灯,射击时会闪烁。您可以在检查器中选择此灯的颜色、长度、强度...。
在下面的脚本中,您有一个关于如何在拍摄期间激活和停用灯光效果的示例。它还控制拍摄之间的时间流逝。没有任何协程。
public Light gunLight;
public float timeBetweenBullets = 0.15f;
void Update ()
{
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If the Fire1 button is being press and it's time to fire...
if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets)
{
Shoot ();
}
// If the timer has exceeded the proportion of timeBetweenBullets that the effects should be displayed for...
if(timer >= timeBetweenBullets * effectsDisplayTime)
{
DisableEffects ();
}
}
public void DisableEffects ()
{
// Disable the line renderer and the light.
gunLight.enabled = false;
}
void Shoot (){
timer = 0f;
// Enable the light.
gunLight.enabled = true;
}
2- 第二部分是如何检测玩家是否朝正确的方向射击。解决这个问题需要在拍摄的时候使用raycast,分析一下光线击中了什么。
为此,您应该使用以下行修改上面的 shot 方法:
void Shoot ()
{
// Reset the timer.
timer = 0f;
// Enable the light.
gunLight.enabled = true;
// Set the shootRay so that it starts at the end of the gun and points forward from the barrel.
shootRay.origin = transform.position;
shootRay.direction = transform.forward;
// Perform the raycast against gameobjects on the shootable layer and if it hits something...
if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
{
// Try and find an EnemyHealth script on the gameobject hit.
EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
// If the EnemyHealth component exist...
if(enemyHealth != null)
{
// ... the enemy should take damage.
enemyHealth.TakeDamage (damagePerShot, shootHit.point);
}
// Set the second position of the line renderer to the point the raycast hit.
gunLine.SetPosition (1, shootHit.point);
}
// If the raycast didn't hit anything on the shootable layer...
else
{
// ... set the second position of the line renderer to the fullest extent of the gun's range.
gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
}
}
现在你的射击方法投射一条射线,如果射线击中敌人(即标记为敌人的游戏对象),它将执行一些动作。在这种特殊情况下,我假设敌人已经附加了一个脚本来减少它被射击时的生命。
您可以使镜头的特效更加复杂,例如:添加声音、渲染的线条、一些模拟粉末的粒子系统...
您可以,而且我认为您应该从 Unity 官方网站查看本教程,以更好地理解我刚才在回答中提到的内容,并为您的游戏获得一些额外的想法:
https://unity3d.com/learn/tutorials/projects/survival-shooter/harming-enemies?playlist=17144
不确定为什么会发生这种情况,但此代码允许在重新加载后发射超过 3 发子弹。我想找出原因。我认为这可能是检查哪个问题之间的时间,但我可能是错的。
如有任何帮助,我们将不胜感激。
public bool isFiring;
public bool isReloading = false;
public BulletController bullet; // Reference another script
public float bulletSpeed; // bullet speed
public float timeBetweenShots; // time between shots can be fired
private float shotCounter;
public Transform firePoint;
public static int ammoRemaining = 3;
public static int maxAmmo = 3;
public Transform ammoText;
// Use this for initialization
void Awake () {
isReloading = false;
ammoRemaining = maxAmmo;
}
// Update is called once per frame
void Update () {
if(isFiring == true )
{
shotCounter -= Time.deltaTime;
if(shotCounter <= 0 && ammoRemaining > 0 && isReloading == false)
{
shotCounter = timeBetweenShots;
BulletController newBullet = Instantiate(bullet, firePoint.position, firePoint.rotation) as BulletController; // creates a new instance of the bullet
newBullet.speed = bulletSpeed;
ammoRemaining -= 1;
ammoText.GetComponent<Text>().text = "Ammo:" + ammoRemaining;
}
}
else if (ammoRemaining == 0)
{
StartCoroutine(Reload());
}
else
{
shotCounter = 0;
}
}
public IEnumerator Reload()
{
isReloading = true;
ammoText.GetComponent<Text>().text = "REL...";
yield return new WaitForSeconds(2);
ammoRemaining = maxAmmo;
isReloading = false;
ammoText.GetComponent<Text>().text = "Ammo:" + ammoRemaining;
}
问题(如讨论的那样)是在您发射最后一枪之后和放开 MouseButton(0) 之前,您的 Reload() 协程在 Update() 中被调用了额外的次数。为避免这种情况,我建议在启动协程之前检查以确保您尚未重新加载:
else if (ammoRemaining == 0 && !isReloading)
{
StartCoroutine(Reload());
}
这是一个题外话,不是为了解决你的问题,而是为了避免你以后出现问题,特别是性能方面的问题。如果您打算开发 3D 射击游戏,我建议您不要实例化子弹(除非您打算创建一些延时场景)
原因有二:
- 您将需要每秒实例化和销毁许多游戏对象
- 如果你给子弹一个逼真的速度,它不应该在 现场
我假设为您实例化子弹的原因主要是以下两个:
- 为了创造一些离开得非常快的视觉效果 按下射击时的枪管
- 检测您是否用
OnCollisionEnter()
或类似的 击中目标
所以我可以给你一些提示,你可以尝试一些东西而不是实例化项目符号。
1- 为了表示射击,您可以在枪管末端安装一盏灯,射击时会闪烁。您可以在检查器中选择此灯的颜色、长度、强度...。
在下面的脚本中,您有一个关于如何在拍摄期间激活和停用灯光效果的示例。它还控制拍摄之间的时间流逝。没有任何协程。
public Light gunLight;
public float timeBetweenBullets = 0.15f;
void Update ()
{
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If the Fire1 button is being press and it's time to fire...
if(Input.GetButton ("Fire1") && timer >= timeBetweenBullets)
{
Shoot ();
}
// If the timer has exceeded the proportion of timeBetweenBullets that the effects should be displayed for...
if(timer >= timeBetweenBullets * effectsDisplayTime)
{
DisableEffects ();
}
}
public void DisableEffects ()
{
// Disable the line renderer and the light.
gunLight.enabled = false;
}
void Shoot (){
timer = 0f;
// Enable the light.
gunLight.enabled = true;
}
2- 第二部分是如何检测玩家是否朝正确的方向射击。解决这个问题需要在拍摄的时候使用raycast,分析一下光线击中了什么。
为此,您应该使用以下行修改上面的 shot 方法:
void Shoot ()
{
// Reset the timer.
timer = 0f;
// Enable the light.
gunLight.enabled = true;
// Set the shootRay so that it starts at the end of the gun and points forward from the barrel.
shootRay.origin = transform.position;
shootRay.direction = transform.forward;
// Perform the raycast against gameobjects on the shootable layer and if it hits something...
if(Physics.Raycast (shootRay, out shootHit, range, shootableMask))
{
// Try and find an EnemyHealth script on the gameobject hit.
EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();
// If the EnemyHealth component exist...
if(enemyHealth != null)
{
// ... the enemy should take damage.
enemyHealth.TakeDamage (damagePerShot, shootHit.point);
}
// Set the second position of the line renderer to the point the raycast hit.
gunLine.SetPosition (1, shootHit.point);
}
// If the raycast didn't hit anything on the shootable layer...
else
{
// ... set the second position of the line renderer to the fullest extent of the gun's range.
gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
}
}
现在你的射击方法投射一条射线,如果射线击中敌人(即标记为敌人的游戏对象),它将执行一些动作。在这种特殊情况下,我假设敌人已经附加了一个脚本来减少它被射击时的生命。
您可以使镜头的特效更加复杂,例如:添加声音、渲染的线条、一些模拟粉末的粒子系统...
您可以,而且我认为您应该从 Unity 官方网站查看本教程,以更好地理解我刚才在回答中提到的内容,并为您的游戏获得一些额外的想法:
https://unity3d.com/learn/tutorials/projects/survival-shooter/harming-enemies?playlist=17144