- Home /
How should I make the projectiles in a fps go straight to the middle of a screen? also, collision problems
I"m trying to make a FPS game using Unity Standard Assets, in which the user shoots arrows with a bow, requiring the arrows to be projectiles (contrary to a raycast-only fps).
I figured out how to make the arrows fire from a point of the bow and go straight somewhere, but what I actually want is making so that the arrows spawn from the bow and go to where the player is aiming (aka the middle of the screen).
I followed some similar questions here on Unity Answers, but for some reason the arrows don't go exactly to where the point is (they actually differ a lot from where the player is aiming). Additionally, sometimes projectile collisions won't register (the arrow sometimes passes through solid objects).
here is the code added code contained in the fps controller script that makes the player shoot arrows:
Ray ray = m_Camera.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0)); RaycastHit hit; // Check whether your are pointing to something so as to adjust the direction Vector3 targetPoint; if (Physics.Raycast(ray, out hit)) targetPoint = hit.point; else targetPoint = ray.GetPoint(1000); // You may need to change this value according to your needs // Create the bullet and give it a velocity according to the target point computed before
GameObject arrowProjectile = Instantiate(m_ArrowPrefab, m_ArrowSpawn.position, m_ArrowPrefab.transform.rotation);
Quaternion rotationOffset = Quaternion.Euler(270f, 0f, 0f);
arrowProjectile.transform.rotation = m_Camera.transform.rotation * rotationOffset;
Rigidbody arrowRB = arrowProjectile.GetComponent<Rigidbody>();
m_ArrowList.Add(arrowProjectile);
arrowRB.velocity = (targetPoint - m_ArrowSpawn.transform.position).normalized * m_ShootForce;
//arrowRB.velocity = m_Camera.transform.forward * m_ShootForce;
UpdateArrowCount() // Checks if arrowList is full. If yes, destroy the oldest arrow object
and here is the code contained in a script attached to the arrow prefab:
public class Arrow : MonoBehaviour
{
[SerializeField] private Rigidbody arrowRB;
[SerializeField] private Collider arrowCollider;
private bool hitSomething = false;
Quaternion m_RotationOffset;
void Start()
{
//arrowRB = GetComponent<Rigidbody>();
m_RotationOffset = Quaternion.Euler(270f, 0f, 0f);
transform.rotation = Quaternion.LookRotation(arrowRB.velocity) * m_RotationOffset;
}
void Update()
{
if (!hitSomething)
{
transform.rotation = Quaternion.LookRotation(arrowRB.velocity) * m_RotationOffset;
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.tag == "Player" || collision.gameObject.tag == "MainCamera")
{
Physics.IgnoreCollision(collision.collider, arrowCollider);
}
if (collision.collider.tag != "Arrow" && collision.collider.tag != "Player" && collision.collider.tag != "MainCamera")
{
hitSomething = true;
arrowRB.constraints = RigidbodyConstraints.FreezeAll;
}
}
}
Answer by unity_ek98vnTRplGj8Q · Jun 29, 2020 at 10:26 PM
Your aiming code looks fine to me; I'm suspicious that your arrow is colliding with something that is altering the trajectory of it. I notice in your "OnCollisionEnter" script you tell the arrow collider to ignore the player and main camera colliders, but you only do it after it has already collided with them and has already altered the physics trajectory. Physics.IgnoreCollision will ignore any FUTURE collisions between the specified colliders, but will not retroactively ignore collisions that have already happened. I recommend you either use Physics.IgnoreCollision() when spawning the arrow, use physics layers and unity's collision matrix in the physics options to ignore collisions between the arrow and the player (this is the easiest to do), or move your arrow spawn point forward so that it doesn't collide with the player on spawn.
As far as your arrow passing through objects - you can still use Raycasting for projectiles. A common practice is to keep track of the arrow's positions each frame as well as its previous position from the frame before then raycast between the two positions to check for a collision. This way your arrow still flies with the same velocity as a projectile, but you will see any colliders that your arrow would normally have missed in between frames. You can also try updating the collision detection options on the rigidbody itself, but I've personally had mixed results doing this.
Thank you for your answer! You were right, the arrow was indeed coliding with the player, and thus changing trajectories. I used unity's collision matrix and the problem is gone. About arrows passing through objects:I will try your suggestion to see if it works. I did realize, however, that removing those collisions actually makes it happen more rarely now.
Your answer
Follow this Question
Related Questions
Dragrigidbody help 1 Answer
Projectiles, their speed, and collisions 1 Answer
Bounce when hitting wall 2 Answers
Gun Fire, sparks on Collision 1 Answer
Bullet projectiles with collision info without affecting others 0 Answers