Search Unity

Help using real bullet physics instead of Raycast

Discussion in 'Scripting' started by the_Bad_Brad, Oct 9, 2015.

  1. the_Bad_Brad

    the_Bad_Brad

    Joined:
    Nov 2, 2014
    Posts:
    278
    I have successfully used Ray Cast for bullets but I want to be more realistic and use real bullet physics instead.
    I have one problem, the collision, sometimes the bullet collision is not detected.

    How do I solve this issue?

    Here is the C# code for the bullet:


    using UnityEngine;
    using System.Collections;

    public class AP_Sabot : MonoBehaviour {
    public float speed = 1f;
    public ParticleSystem railgun_ap_round_vfx;
    public AudioSource railgun_ap_round_sfx;




    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
    transform.Translate (0, 0, speed);


    }
    void OnCollisionEnter(Collision collision) {
    railgun_ap_round_vfx.Play ();
    railgun_ap_round_sfx.Play ();

    }
    }
     
  2. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    depending on the speed of the bullet you will have to do a small capusulecast or raycast infront of the bullet.

    But also you might want to not use transform.Translate to do this, but set the velocity on the bullets rigid body instead so the physics system is in control of moving the bullet not the transform.
     
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,775
    To be honest.... you solve that issue by using a raycast bullet.

    Can I ask what your goal is in using a "real physics" bullet instead of a raycasted one?
     
  4. aLovedHater

    aLovedHater

    Joined:
    Oct 12, 2014
    Posts:
    16
    Maybe he wants to use Physics instead of raycasting for slower types of bullet firing to make it more realistic. (such as if the gun were a rocket launcher or if you were throwing grenades. If this is the case then you should have no problem with collision detection, but if you're using physics for a bullet going too fast than it will often say.. go through the object that you fire it at and completely ignore collision. (this is why you have to raycast fast moving bullets, since physics simply won't work for those types of bullets)

    Here's something that might help you get started with using physics with bullets:

    float bulletImpulse = 20.0f // you got this right, but using 1f would make it a pretty slow bullet...
    public GameObject FIRINGPOINT; //this is where your bullet will spawn
    public GameObject BULLET_PREFAB; //this is the bullet in your prefabs that will spawn on your FIRINGPOINT

    //Now that we've declared everything we need, lets get to firing the bullet!

    if (Input.GetKeyDown (KeyCode.T) ) //assuming you fire with a T button for whatever reason
    {
    //combine what will spawn with where it will spawn "whatspawns,where at what position, //where at what rotation"
    GameObject theRocket = (GameObject) Instantiate (BULLET_PREFAB, FIRINGPOINT.transform.position, FIRINGPOINT.transform.rotation);

    //now that our bullet has spawned, lets use Physics to move the bullet.

    // This will get the rocket's rigidbody and add force from where it spawns, pushing it foward at //our speed that we chose (bulletImpulse) using ForceMode(a way to apply a force using a //Rigidbody
    theRocket.GetComponent<Rigidbody> ().AddForce (FIRINGPOINT.transform.forward * bulletImpulse, ForceMode.Impulse
    }

    now you can put a script on your bullet prefab that will be spawned and pushed at a force to make it collide with things =)

    For example,

    void OnCollisionEnter (Collision collision)
    {
    if(collision.gameObject.tag == "Enemy")
    {
    // here, after the bullet collides with the enemy you can make it do an endless amount of things..
    }
    }
     
  5. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Code tags people!!!

    To the OP: Never use Transform.Translate for physics enabled rigidbody objects. The most accurate way to simulate a bullet is simply to set Rigidbody.velocity on the first frame it's fired. The engine will take care of gravity and air resistance and ricochets for you.

    If your bullet is moving too fast it may miss collisions. To solve this you can mess with the collision mode. Or you can do a raycast to catch the 'between frames' movement.
     
    McMayhem likes this.
  6. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    It's pretty much a certainty that it will miss collisions if it goes anywhere near actual bullet velocity.

    For bullets, your AddForce (assuming you use Impulse) has to be pretty darn high. Assuming you're multiplying by a simple forward vector, you're looking at anywhere from 115 - 130 * transform.forward. At that speed, it doesn't matter whether or not the collision detection is set to Discreet/Continuous/Continuous Dynamic, it's still going to pass through walls and other objects.

    The physics system isn't meant to handle forces of that magnitude.

    You can simulate bullet physics with a raycast bullet using simple vector mathematics. It's a little extra work and you don't get to fool around with the fun tools Unity has for physics and rigidbodies, but it's pretty much your only hope in this scenario.
     
    Ironmax likes this.
  7. the_Bad_Brad

    the_Bad_Brad

    Joined:
    Nov 2, 2014
    Posts:
    278
    I want to have that bullet time effect on sniper rifles.
     
  8. the_Bad_Brad

    the_Bad_Brad

    Joined:
    Nov 2, 2014
    Posts:
    278
    Alright guys, thanks for the tip. I'll use these as reference when I got a chance to work on bullet physics again.
     
  9. Ironmax

    Ironmax

    Joined:
    May 12, 2015
    Posts:
    890
    You can use 2 raycasts with hit.distance and gravy.
     
  10. Major

    Major

    Joined:
    Jul 26, 2012
    Posts:
    69
    I know this is an old post, but I feel that this could be helpful for somebody. This is my raycast bullet physics code. I've done my best to make it as simple as possible. This works by spawning an object with this script attached, everything else is taken care of.

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.        
    5. public class BulletPhysics : MonoBehaviour {
    6.      public float gravity = -9.81f;
    7.      public float velocity = 350;
    8.      public float maxTime = 5f;
    9.  
    10.      private Vector3 origin;
    11.      private Vector3 cameraDir;
    12.      private float increment = 0;
    13.        
    14.      void Start(){
    15.            origin = transform.position;
    16.            cameraDir = Camera.main.transform.forward;
    17.      }
    18.        
    19.      void FixedUpdate () {
    20.           //displacement = v0*t + 0.5at^2 + origin
    21.           //Debug.DrawLine (disp(increment), disp(increment + 0.02f), Color.red, 10);
    22.           RaycastHit hit;
    23.        
    24.           if (Physics.Linecast(disp(increment), disp(increment + 0.02f), out hit)) {
    25.                Destroy (gameObject);
    26.           }
    27.        
    28.           if (increment > maxTime)
    29.                Destroy (gameObject);
    30.        
    31.           transform.position = disp (increment + 0.02f);
    32.           increment += 0.02f; //<--- fixedupdate time (value in Time settings)
    33.      }
    34.        
    35.      Vector3 disp (float t){
    36.            Vector3 vel = velocity * cameraDir;
    37.            Vector3 disp = origin + vel * t - (playerDown * Mathf.Pow (t, 2) * gravity * 0.5f - Vector3.up * t);
    38.            return disp;
    39.      }
    40. }
    41.