Search Unity

Can't raycast from newly instantiated objects?

Discussion in 'Editor & General Support' started by jtsmith1287, Jun 25, 2018.

  1. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    I have projectiles flying at a very fast rate, and to avoid a bunch of ugly physics I have the projectile raycast in front of it every frame as far as it will travel until the next frame and return whatever object it will collide with. It works perfectly, but I'm seeing that the first few frames after instantiating the projectile no collisions are being detected.

    The projectile object is just a transform, projectile script I wrote and a trail renderer. I've tested this by firing at point blank and slowly backing up. At first the projectiles just pass right through but after a certain distance they never miss and work flawlessly. This isn't an issue with discrete or continuous collisions or anything because there's no rigidbody or collider.

    My thought is that there's maybe a "wake up" time on objects before they can raycast? Is there any such thing like this? Or does anyone have any ideas on what might be happening here?
     
  2. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    GameObjects do not raycast per se, Physics.Raycast is a static function that does not take a reference to a gameobject.

    Try using Debug.DrawRay to draw the ray and check the origin/direction of the ray is correct, and Debug.Log to check that the Raycast is being performed by the script on the bullet.

    Can you post your bullet script?
     
  3. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    @bobisgod234 Ya it works correctly as long as I'm about 10-15 meters away from whatever I'm hitting. So the raycast is working. I'll post the code but I'm 99% sure it's not in the code. It's something to do with

    Code (CSharp):
    1. public class Projectile : MonoBehaviour {
    2.  
    3.     /// <summary>
    4.     /// The object that fired the projectile
    5.     /// </summary>
    6.     public GameObject Owner;
    7.     public int Speed;
    8.  
    9.     /// <summary>
    10.     /// True if the projectile will collide this frame or the next frame.
    11.     /// </summary>
    12.     private bool collided;
    13.     /// <summary>
    14.     /// The object the projectile is colliding with.
    15.     /// </summary>
    16.     private Collider collider;
    17.  
    18.     /// <summary>
    19.     /// Runs every frame.
    20.     /// </summary>
    21.     private void Update() {
    22.  
    23.         if (!collided) {
    24.             DoMoveForward();
    25.             CheckForCollisions();
    26.         } else {
    27.             DoCollision(collider);
    28.         }
    29.     }
    30.  
    31.     /// <summary>
    32.     /// Checks if the projectile will collide with an object next frame.
    33.     /// </summary>
    34.     private void CheckForCollisions() {
    35.  
    36.         RaycastHit hitInfo;
    37.         if (Physics.Raycast(transform.position, transform.forward, out hitInfo, Speed * Time.deltaTime)) {
    38.             collided = true;
    39.             collider = hitInfo.collider;
    40.         }
    41.     }
    42.  
    43.     /// <summary>
    44.     /// Moved the projectile positively along the Z axis a distance equal to its speed per second.
    45.     /// </summary>
    46.     private void DoMoveForward() {
    47.  
    48.         transform.position += (transform.forward * Speed * Time.deltaTime);
    49.     }
    50.  
    51.     /// <summary>
    52.     /// Handles the collision and deals damage if applicable. If the object cannot be damaged nothing happens.
    53.     /// </summary>
    54.     /// <param name="other"></param>
    55.     private void DoCollision(Collider other) {
    56.  
    57.         Destructable d = other.gameObject.GetComponent<Destructable>();
    58.  
    59.         if (d != null) {
    60.             Ship target = other.GetComponent<Ship>();
    61.             Ship attacker = Owner.GetComponent<Ship>();
    62.             int damage = attacker.Weapon.Damage;
    63.             float mitigation = 0;
    64.  
    65.             if (target != null) {
    66.                 // A weapon can never deal damage over base, but can be reduced to below 100%
    67.                 mitigation = Mathf.Min(1, attacker.Weapon.Power / (float)target.Hull.Armor);
    68.                 damage = Mathf.CeilToInt(attacker.Weapon.Damage * mitigation);
    69.             }
    70.  
    71.             d.Damage(damage, Owner.GetComponent<Destructable>());
    72.  
    73.             Debug.Log(string.Format("{0} dealt {1} damage to {2}, {3} damage reduced by {4}% ({5} Power vs {6} Armor)",
    74.                 attacker.name, damage, other.name, attacker.Weapon.Damage, 100 - (mitigation * 100), attacker.Weapon.Power,
    75.                 target != null ? target.Hull.Armor : 0));
    76.             gameObject.SetActive(false);
    77.         }
    78.     }
    79. }
     
  4. bobisgod234

    bobisgod234

    Joined:
    Nov 15, 2016
    Posts:
    1,042
    You move the bullet forward, then check if there are any collisions infront of the bullet. This seems backwards, you want to check for collisions first before moving.

    Try swapping the functions around in Update():

    Code (CSharp):
    1.     private void Update() {
    2.         if (!collided) {
    3.             CheckForCollisions();
    4.             DoMoveForward();
    5.         } else {
    6.             DoCollision(collider);
    7.         }
    8.     }
     
  5. jtsmith1287

    jtsmith1287

    Joined:
    Aug 3, 2014
    Posts:
    787
    You're a gentleman and a scholar. Here I am saying it's not my code and low and behold. That did the trick. Much thanks good sir!