Instantiating with reference to parent

Options
Hi

I am instantiating a bullet when i fire:

GameObject bullet = PhotonNetwork.Instantiate("Bullet", gunTurrentLeft_position.transform.position, gunTurrentLeft_position.transform.rotation, 0);

Because the bullet comes out from within the player's collider, i needed to ignore it so it won't hit it, so on the bullet prefab i have a script:

Physics.IgnoreCollision(capsuleCollider, myPlayer.GetComponentInChildren<BoxCollider>());
capsuleCollider is the bullet's collider.

The problem is, on the observer client the bullet does hit the shooting player's collider.
I'm trying to find a way to reference the parent gameobject that instantiated the prefab and set it as "myPlayer" so it would reference the currect player's collider on all observers.

I can't pass a gameobject on the instantiate method because it only excepts primitives.

Comments

  • vadim
    Options
    Hi,

    Do you run call Physics.IgnoreCollision on all clients?

    Why do you handle collisions on both sides?
    Do this on shooting client only and notify others about hit. Or you will get game state out of sync after few shots.

    Also bullets usually does not require PhotonView since there is nothing to synchronize for them. If you need to visualize them, simulate position locally basing on initial shot parameters passed in "shot" RPC.
  • I was able to solve this after a few hours of trying different methods, but i'm not sure if the way i work is "best practice".
    I will try to write in more detail how i'm doing it:

    1. I have an 'actions' script on my player. when i shoot i call PhotonNetwork.instantiate for the 'bullet' prefab.
    Then, i immediatly call an RPC on the PhotonView of the 'bullet' prefab:
    GameObject bullet = PhotonNetwork.Instantiate("Bullet", gunTurrentLeft_position.transform.position, gunTurrentLeft_position.transform.rotation, 0);
    
    bullet.GetComponent&lt;PhotonView&gt;().RPC("disableSelfCollision", PhotonTargets.All, photonView.viewID);
    

    2. The method 'disableSelfCollision" on the 'bullet' prefab is looping through all of the players on the scene looking for the one with the photonView.viewID that was passed to the method, then disables the collision between the bullet and that initiator's colliders, and adds force to move the bullet forward (if i don't add force on all of the clients, and just do it on the player's client and position-sync on all observers, then i won't get the collision triggered on the observers and all of the logic i have on item number 3 won't happen.

    If i don't disable the collision on all clients, it will hit the colliders of the player that is doing the shooting on the observer clients.
        &#91;RPC&#93;
        void disableSelfCollision(int photonViewID)
        {
            
    
            GameObject&#91;&#93; players = GameObject.FindGameObjectsWithTag("Player");
    
            GameObject instantiatorPlayer = null;
            foreach (GameObject player in players)
            {            
                if (player.GetPhotonView().viewID == photonViewID)
                {                
                    instantiatorPlayer = player;
                }
            }
    
            if (instantiatorPlayer != null)
            {
                // disable collision with player's box collider so the bullet could get out
                Physics.IgnoreCollision(capsuleCollider, instantiatorPlayer.GetComponentInChildren&lt;BoxCollider&gt;());
                Physics.IgnoreCollision(capsuleCollider, instantiatorPlayer.GetComponentInChildren&lt;MeshCollider&gt;());
            }
    
            // add force to the bullet's rigidbody
            rb.AddForce(transform.forward * bulletSpeed, ForceMode.Impulse);
        }
    


    3. On the 'bullet' prefab, I have an OnCollisionEnter which instantiates (not network-instantiates) an explosion at the point of impact. since ths prefab is already network-instantiated, this will show on all clients too.
    And if the collider that was hit, belongs to the current player, I update his health status on all clients.
        void OnCollisionEnter(Collision collision)
        {
            
            // show explosion particle emitter at the point of impact
            ContactPoint contact = collision.contacts&#91;0&#93;;        
            Vector3 pos = contact.point;
            Instantiate(explosion, pos, collision.gameObject.transform.rotation);
    
    
            // if we hit a player
            if (collision.gameObject.tag == "Player")
            {
    
                // if current player got hit - update everyone with it's new health status                
                if (collision.gameObject.GetPhotonView().isMine)
                {                
                    collision.gameObject.GetPhotonView().RPC("updateHealth", PhotonTargets.All, collision.gameObject.GetComponent&lt;NetworkPlayerScript&gt;().playerHealth - 1);
                }
            }
    
            // destroy bullet after collision
            Destroy(gameObject);
            
    
        }
    


    This is my first multiplayer game, so if there is a more efficient way of doing this, by all means...
  • vadim
    Options
    Did you try 'bullet' best practice I described in my previous post?

    Also you can find a lot searching the forum. The 'bullet' topic is quite hot here.
  • You suggested that the player doing the shooting does the update about the result of his shooting, and update the bullet positions on the observers instead of network-instantiate them. (is there an efficiency difference between network-instantiating an object, and making an RPC call for all clients?)

    but then, I would loose the collision event on each client and I would have to network-instantiate the explosion prefab whenever a player got hit so he sees it at the point of impact the same way the player doing the shooting does. right now this is done locally since i instantiate the bullet.
    so I'm not sure if that would save anything network-wise.

    I was also thinking that for security purposes it might be better to let the person that got hit update the other clients that he got hit instead of the one doing the shooting.
    Since I'm using cloud and the logic is not server-side I thought I should probably expect hackers to put a network sniffer on the traffic going out of their network and i should probably limit the importance of the data going out as opposed to data coming in, that way if they make any change to the incoming stream, they are the only one's affected.
  • vadim
    Options
    Single RPC call is much more efficient than instantiating and synchronization of object.

    You do not need network-instantiate explosion. Spawn it locally on 'hit' RPC.
    Or instantiate bullets locally on 'shoot' RPC and enable collision detection for them. Handle collisions to spawn explosions but not for hit logic.

    The point is to detect hit only once. This can be done on any client including one that got hit. But it can cheat too.