Search Unity

[SOLVED] (doubt) Make bullet avoid collision with owner

Discussion in 'Physics' started by PJRM, Nov 14, 2017.

  1. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    303
    So i'm in a tough situation where i'm using a pool to preload, spawn and despawn bullets.
    Here is the thing:
    Code (CSharp):
    1. namespace Game.Units {
    2.    [RequireComponent (typeof(PoolObject), typeof(Collider))]
    3.    public class Bullet : MonoBehaviour {
    4.       private PoolObject poolObject;
    5.       private GameObject owner;
    6.  
    7.       private void Awake () {
    8.          poolObject = GetComponent<PoolObject> ();
    9.       }
    10.       private void OnCollisionEnter (Collision collision) {
    11.          IDamagable damagableObject = collision.gameObject.GetComponent<IDamagable>();
    12.          if (damagableObject != null) {
    13.             damagableObject.Damage(damage);
    14.          }
    15.       }
    16.  
    Code (CSharp):
    1. namespace Game.Units {
    2.    public interface IDamagable {
    3.       void Damage(int amount);    
    4.    }
    5. }
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. namespace Game.Utils.Poolv1 {
    7.    [Serializable]
    8.    public class Pool {
    9.       [SerializeField]private PoolObject _prefabObject;
    10.       [SerializeField]private int _minPreload = 1;
    11.       private Stack<PoolObject> _inactive;
    12.       private GameObject _parent;
    13.  
    14.       public void SetPrefabObject(PoolObject prefab) {
    15.          if (prefab != null)
    16.             _prefabObject = prefab;
    17.       }
    18.  
    19.       /// <summary>
    20.       /// Init this instance.
    21.       /// </summary>
    22.       public void Init () {
    23.          if (_prefabObject == null) {
    24.             Debug.LogError (_prefabObject.name + " is not a poolable object, make sure it have IPoolable interface!");
    25.             return;
    26.          }
    27.  
    28.          _inactive = new Stack<PoolObject> ();
    29.          Preload ();
    30.       }
    31.  
    32.       /// <summary>
    33.       /// Sets the parent.
    34.       /// </summary>
    35.       /// <param name="parent">Parent.</param>
    36.       public void SetParent (GameObject parent) {
    37.          _parent = parent;
    38.       }
    39.  
    40.       public void Pop (Vector3 position, Vector3 eulerAngles, Action<GameObject> OnPopEvent) {
    41.          if (_inactive.Count > 0) {
    42.             // there is an object on the pool
    43.             PoolObject poped = _inactive.Pop ();
    44.             poped.transform.SetParent (null);
    45.             poped.transform.position = position;
    46.             poped.transform.eulerAngles = eulerAngles;
    47.             poped.OnPop = OnPopEvent;
    48.             poped.Pop ();
    49.          } else {
    50.             CreatePoolableUnit ();
    51.             Pop (position, eulerAngles, OnPopEvent);
    52.          }
    53.       }
    54.  
    55.       public void Push (PoolObject unit) {
    56.          InnerPush (unit);
    57.       }
    58.  
    59.       private void InnerPush (PoolObject unit) {
    60.          unit.transform.position = Vector3.zero;
    61.          unit.transform.rotation = Quaternion.identity;
    62.          unit.transform.SetParent (_parent.transform);
    63.          unit.gameObject.SetActive (false);
    64.          _inactive.Push (unit);
    65.       }
    66.  
    67.       private void CreatePoolableUnit () {
    68.          PoolObject unit = MonoBehaviour.Instantiate<PoolObject> (_prefabObject);
    69.          unit.SetPool (this);
    70.          InnerPush (unit);
    71.       }
    72.  
    73.       /// <summary>
    74.       /// Preload the pool of IPoolable objects
    75.       /// </summary>
    76.       private void Preload () {
    77.          for (int i = 0; i < _minPreload; i++) {
    78.             CreatePoolableUnit ();
    79.          }
    80.       }
    81.    }
    82.  
    83.    public class UnitPool : MonoBehaviour {
    84.       public Pool _pool;
    85.       private GameObject _parent;
    86.  
    87.       public void Pop (Vector3 position, Vector3 eulerAngles, Action<GameObject> OnPopEvent = null) {
    88.          _pool.Pop (position, eulerAngles, OnPopEvent);
    89.       }
    90.  
    91.       private void Start () {
    92.          _parent = new GameObject ("Pool");
    93.          _parent.transform.position = Vector3.zero;
    94.          _parent.transform.rotation = Quaternion.identity;
    95.          _parent.transform.SetParent (transform);
    96.  
    97.          _pool.SetParent (_parent);
    98.          _pool.Init ();
    99.       }
    100.    }
    101. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System;
    5.  
    6. namespace Game.Utils.Poolv1 {
    7.    public class PoolObject : MonoBehaviour, IPoolable {
    8.       public Action<GameObject> OnPop;
    9.       private Pool _poolOwner;
    10.  
    11.       public void Despawn() {
    12.          _poolOwner.Push(this);
    13.       }
    14.  
    15.       public void SetPool(Pool pool) {
    16.          _poolOwner = pool;
    17.       }
    18.  
    19.       #region IPoolable implementation
    20.       public void Pop () {
    21.          gameObject.SetActive(true);
    22.          if (OnPop != null)
    23.             OnPop(gameObject);
    24.       }
    25.       #endregion
    26.      
    27.    }
    28. }
    Code (CSharp):
    1. namespace Game.Utils.Poolv1 {
    2.    public interface IPoolable {
    3.       void Pop ();
    4.    }
    5. }
    Code (CSharp):
    1. namespace Game.Units {
    2.    [RequireComponent(typeof(Rigidbody), typeof(WeaponController), typeof(Collider))]
    3.    public class BaseShip : MonoBehaviour, IDamagable {
    4.       #region IDamagable implementation
    5.  
    6.       public void Damage (int amount) {
    7.          Debug.Log(gameObject.name+": Taking "+amount.ToString()+" damage!");  
    8.       }
    9.  
    10.       #endregion
    11.  
    I have a weapon scriptableObject that on Awake, it pass through the bullet prefab to my pool to be preloaded.

    the problem: Both my player and Enemy uses BaseShip! Layer Collosion is not solving the issue since I need the bullet from my enemy to ignore it's owner which is the enemy.

    I really want a way to say to each bullet = ignore the collision from the owner. but so far no clue.
     
  2. KeithKong

    KeithKong

    Joined:
    May 31, 2015
    Posts:
    73
    Checkout Physics.IgnoreCollision. You can pass in two specific colliders that will ignore each other. You can ignore the spawning bullet and spawning weapon collider and later pass them in again with "false" as the third parameter to reenable collision between the two objects.
     
  3. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    303
    Even thought i tried to do that before, I manage to work around and set up the collisionIgnore between them.

    Thank you!
     
  4. KeithKong

    KeithKong

    Joined:
    May 31, 2015
    Posts:
    73
    Yup yup! :) Just make sure you always remove the ignore pairs. Since you are pooling objects, even if you don't need the source weapon and bullet to ever collider you may find future recycled bullets randomly not colliding with other weapons.