Unity项目中子弹反向射向玩家的技术求助
问题分析与解决方案
核心问题
子弹反向射向玩家的最可能原因是**cursorPosition的获取方式错误**,导致Fire方法传入的targetPosition并非鼠标在世界空间中指向的正确位置,而是指向了玩家/相机所在位置,最终子弹LookAt这个点后朝向玩家发射。
比如如果你的cursorPosition是通过Camera.main.ScreenToWorldPoint(Input.mousePosition)直接获取的,由于Input.mousePosition的Z值为0,透视相机下会返回相机自身的位置(第一人称视角下就是玩家位置),子弹自然会反向射向玩家。
修复步骤
- 替换
cursorPosition的获取逻辑,改用射线检测获取鼠标在场景中的命中点:
// 在PlayerBehaviour中获取cursorPosition的代码 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out RaycastHit hitInfo)) { cursorPosition = hitInfo.point; }
- 确保场景中有可被射线检测的地面/碰撞体(比如给地面添加
Collider组件)。
额外排查点
- 检查子弹预制体的
Transform轴方向:确保子弹的Z轴(默认forward方向)与模型前进方向一致,如果模型的前进方向是X轴,需要调整代码为ourRigidBody.velocity = transform.right * bulletSpeed; - 确认武器的
transform.forward确实指向前方:可以在Scene视图中选中武器GameObject,查看Gizmos的蓝色轴(forward)方向是否正确。
原问题代码
WeaponBehaviour.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class WeaponBehaviour : MonoBehaviour { public GameObject bulletPrefab; public float secondsBetweenShots; float secondSinceLastShot; public float accuracy; // if accuracy is 0, the game will crash public float numberOfProjectiles; public AudioSource audioSource; public float kickAmount; // Start is called before the first frame update void Start() { secondSinceLastShot = secondsBetweenShots; audioSource = GetComponent<AudioSource>(); } // Update is called once per frame void Update() { //firing secondSinceLastShot += Time.deltaTime; } public void Fire(Vector3 targetPosition) { if (secondSinceLastShot > secondsBetweenShots) { //ready to fire Debug.Log("T" + targetPosition); //this next line makes it so that when you fire your weapon, the enemies immediately start spawning references.levelManager.alarmSounded = true; audioSource.Play(); references.screenshake.joltVector = transform.forward * -kickAmount; for ( int iterationCount=0; //declare a variable to keep track of how many iterations we've done iterationCount < numberOfProjectiles; //set a limit for how high this variable can go iterationCount++ //run this after each time we iterate - increase the iteration count ) { GameObject newBullet = Instantiate(bulletPrefab, transform.position + transform.forward, transform.rotation); //offset that target position by a random amount according to our inaccuracy float inaccuracy = Vector3.Distance(transform.position, targetPosition) / accuracy; Vector3 inaccuratePosition = targetPosition; inaccuratePosition.x += Random.Range(-inaccuracy, inaccuracy); inaccuratePosition.z += Random.Range(-inaccuracy, inaccuracy); newBullet.transform.LookAt(inaccuratePosition); Debug.Log(inaccuratePosition); secondSinceLastShot = 0; //newBullet.name = iterationCount.ToString(); } } } }
BulletBehaviour.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BulletBehaviour : MonoBehaviour { public float bulletSpeed; public float secondsUntilDestroyed; public float damage; // Start is called before the first frame update void Start() { Rigidbody ourRigidBody = GetComponent<Rigidbody>(); ourRigidBody.velocity = transform.forward * bulletSpeed; //rigidbody.velocity = transform.forward * bulletSpeed; } // Update is called once per frame protected virtual void Update() { secondsUntilDestroyed -= Time.deltaTime; if (secondsUntilDestroyed < 1) { transform.localScale *= secondsUntilDestroyed; } if (secondsUntilDestroyed < 0) { Destroy(gameObject); } } private void OnCollisionEnter(Collision thisCollision) { GameObject theirGameObject = thisCollision.gameObject; //after thisCollision. the options are GetEnumerator, GetHashCode, GetType, impactForceSum, impulse, other, relativeVelocity //rigidBody, ToString, contacts, Equals, frictionForce\sum, gameObject, GetContact, GetContacts. //them.TakeDamage(1;) HealthSystem theirHealthSystem = theirGameObject.GetComponent<HealthSystem>(); if (theirHealthSystem != null) { theirHealthSystem.TakeDamage(damage); } Destroy(gameObject); } }
PlayerBehaviour 触发射击代码片段
if( weapons.Count > 0 && Input.GetButton("Fire1")) { //tell our weapon to fire weapons[selectedWeaponIndex].Fire(cursorPosition); }
内容的提问来源于stack exchange,提问作者Arcader Master
相关产品推荐
相关产品推荐

