Search Unity

Destroy Projectile for all players

Discussion in 'Multiplayer' started by LDawson97, Jan 1, 2019.

  1. LDawson97

    LDawson97

    Joined:
    Aug 16, 2018
    Posts:
    19
    Hello. I'm building a mini RTS where players units can fire at each other. It all works good so far.

    I'm a little stuck when it comes to destroying the projectiles belonging to each player. Each projectile is synced accross the network with a NetworkTransform component. I have attempted a number of possible solutions such as removing all non-network components, then the network components. I have tried RPC calls and calling the Destroy function on the server machines for all projectiles that I need destroyed. Neither of these work :(

    I can't seem to find much documentation on this and not many forum posts.

    I try to use
    NetworkServer.Destroy();

    but I always get the following error:
    Received NetworkTransform data for GameObject that doesn't exist


    The unit is responsible for destroying the projectile. Here is my code on the unit, hit by the projectile.
    OurPlayerMGR is a reference to the Players' Player Prefab found in the Network Manager
    :
    Code (CSharp):
    1. private void OnTriggerEnter(Collider other)
    2.     {
    3.         if (!hasAuthority) return;
    4.         if (!other.tag.Contains("Projectile")) return;
    5.         if (other.gameObject.GetComponent<NetworkIdentity>().hasAuthority) return;
    6.        
    7.         Vector3 CP = other.ClosestPoint(MyHitboxCollider.transform.position);
    8.         if (isPositionInBounds(CP, MyHitboxCollider))
    9.         {
    10.             OurPlayerMGR.CmdDestroyObject(other.gameObject);
    11.         }
    12.     }

    The method used to destroy the object, found on the Players' Player prefab:
    Code (CSharp):
    1.  
    2. [Command]
    3. public void CmdDestroyObject(GameObject UnitToDestroy)
    4. {
    5.      NetworkServer.Destroy(UnitToDestroy);
    6. }
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    An easy way would be to give all projectiles a common tag, and set a value on a component saying who fired it, and on the server when a player disconnects you loop through all projectiles and destroy all projectiles fired by the disconnected player. Not very efficient, but easy to implement, and won't have to happen often if you don't have players disconnecting all the time.

    You could also maintain a list of each projectile each player has fired on the Player GameObject on the server, and in OnDestroy on the Player GameObject you just destroy all projectiles in the list.
     
    LDawson97 likes this.
  3. LDawson97

    LDawson97

    Joined:
    Aug 16, 2018
    Posts:
    19
    Sorry I didn't explain it very clearly. I need the projectiles to destroy once they hit the enemy unit, not when the player disconnects. I suppose I could just change the tag so the above argument would evaluate to false. However, this would only be a temporary solution.

    It's a shame the documentation doesn't tell me anything about NetworkTransform data and how to manage it. I think the problem is the use of NetworkTransform. Since this syncs movement on its own, there is no way to stop it. Disabling the componenet itself or setting the Send Rate of the projectile doesn't stop the sending of data. I think using Rpc's and then destroying the RPCs may work.
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Oh I understand now. So you are using client authority for bullets, which means the NetworkTransform will sync the position of the bullet from the client to the server. You then send a Command to the server to destroy the bullet. When the server receives the Command it destroys the bullet immediately, and before the client receives the message to destroy the bullet locally it is sending another position update to the server or one was already either in transit or in the send queue. The server receives that position update, and adds a log message that it received the data for an object that no longer exists.

    I believe this is expected behavior. If it really bugs you I'd try disabling the NetworkTransform component of the bullet on the client side just before calling CmdDestroyObject, and setting ConnectionConfig.SendDelay to 0 so you're not holding transform sync messages in the outbound queue. That might work.

    https://docs.unity3d.com/ScriptReference/Networking.ConnectionConfig.SendDelay.html
     
    Last edited: Jan 3, 2019
    LDawson97 likes this.
  5. LDawson97

    LDawson97

    Joined:
    Aug 16, 2018
    Posts:
    19
    Yeah essentially that was my idea. I managed to solve the problem of destroying the objects easily now.

    It turns out I just needed to stop manipulating the object before destroying it. Since the bullets had a Translate movement applied to them, this meant the movement was applied constantly. . Also, each projectile was in a manager from the firing unit, so this made things complicated. For example, the object was moved in the loop but this meant that if I were to destroy it, I would have to break in the loop. It was more of a faf on.

    I made it so the projectile manages iteself so now if it collides with a unit, it has a bool ticked. Simply, if it's unticked, it applies movement. Else, the object destroys itself. It's far more simple.

    You can freely destroy things as long as you satisfy two things:
    • are not applying anything to them like I was with the velocity.
    • You destroy them using the correct players object
    The data sent over the network must just be a reference to the constant movement I am applying, which would make sense.

    It works great now :)

    Thanks for your input!
     
    Joe-Censored likes this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Another solution you could consider would be to not destroy the bullet on impact at all by implementing pooling for these bullets. So you reset the bullet for future use instead of destroying it.
     
    LDawson97 likes this.
  7. LDawson97

    LDawson97

    Joined:
    Aug 16, 2018
    Posts:
    19
    Possibly but I don't think that would work when there are a many bullets flying at once. I get what you mean though :)