Issue with controlling collision on rigid body instantiated over network

Hi all,

I have a player object that is shooting a missile. On the player side I know who the parent is (the player shooting the weapon), and I can set Physics.IgnoreCollision between the newly instantiated object and the player who fired it. However, once the missile is instantiated on other clients, it immediately collides with the avatar version of the player. Normally I’d send some data as part of the instantiate that contains the network unique parent id of the player object that shot the missile, but I have two issues here:

  1. I don’t see an option in network.instantiate to send additional information
  2. what is the unique global network id of each object

The only thing I can think of is to instantiate the missile far enough in front of the player so it doesn’t collide against its avatar on the remote clients. However, even that is risky as the player could be traveling quite fast and by the time the missile is instantiated it could be colliding with the avatar on the remote client.

Any ideas or suggestions on how best to handle this?

So I got it to work this way, but I don’t know if it’s really a good way or not. I’m not sure if it’ll consistently work, or due to internal networks if two people over the WAN can end up having the same internal network even though they’re different clients, then this could prove insufficient, right?

// If the missile and the hit object share the same ipAddress and the hit game object is a remote
// player, then it must be the player that fired the missile, so don’t collide on yourself
if ( networkView != null gohit.gameObject.networkView != null
networkView.viewID.owner.ipAddress != gohit.gameObject.networkView.viewID.owner.ipAddress
gohit.gameObject.tag == “PlayerRemote” )

Ok so no one ever replied to my post. Maybe because I replied that I had a working alternative, but as I said, I didn’t think it was a clean way to do it. Well through persistence and determination it came to me when I was on the toilet, oh I mean on the phone with my son :J complaining to him how Unity networking works and it occurred to me how to resolve it. It was so obvious. Serves me right for following examples instead of looking to do it the way I know how to do it on other platforms.

I mentioned earlier that on other platforms I’d usually be able to send a network packet with additional information, so I could include what I need in the originating packet, but using Network.Instantiate didn’t support that. What I realized was instead of using Network.Instantiate I could use an rpc and do it all from there.

Originally I was running Network.Instantiate(go_missle, transform.position, transform.rotation,0); My issue was that with this command I couldn’t send any additional information such as who was the parent object, or any other information I might need. What I thought to do was first issue the Network.Instantiate then use an RPC call to pass the information after it was instantiated. As I was thinking through it I realized I could use the RPC for everything including the instantiate, and didn’t need to use Network.Instantiate at all. This way I can use a single command and send the extra information needed. See below for the details of what I did.

So the fix is as follows:

if (TimeToFire >= refire_rate_in_seconds Input.GetMouseButtonUp(1) )
{
NetworkViewID _vid = Network.AllocateViewID();
networkView.RPC( “OnFireMissile”, RPCMode.AllBuffered, _vid, this.networkView.viewID);
}

[RPC]
void OnFireMissile (NetworkViewID _viewId, NetworkViewID _parentViewId)
{
GameObject theMissle = Instantiate(go_missle, transform.position, transform.rotation) as GameObject;
NetworkView nview = (NetworkView)theMissle.GetComponent(typeof(NetworkView));
nview.viewID = _viewId;

if (nview.isMine)
{
NetworkRigidbody _NetworkRigidbody = (NetworkRigidbody) theMissle.GetComponent(“NetworkRigidbody”);
_NetworkRigidbody.enabled = false;
}
else
{
name += “Remote”;
NetworkRigidbody _NetworkRigidbody = (NetworkRigidbody) theMissle.GetComponent(“NetworkRigidbody”);
_NetworkRigidbody.enabled = true;
}

// Both the Player has a subobject for the ship which has a collider and the missle has a subobject for the capsule which has a collider
Physics.IgnoreCollision(transform.GetChild(0).collider, theMissle.transform.GetChild(0).collider); // don’t collide with ourselves
}

Try to make the “right” way: If you shoot a missile it can not reach the person who released, since the speed is higher.

“Good” solution for me: Put a delay based on the speed of the player, so when time passes the object may touch its owner (You can do this without interacting with the network, since it is a standard action for every player and if will hack the worst thing that can happen is that the missile does not collide with it ever)

I hope I helped you

Thanks Yokil. I originally thought of a delay but then if I were trying to dumb fire the missile at an enemy right on top of me it might go right through them too, so I opted not to go that route.

Furthermore, it’s NOT really about how to best fire a missile. The issue was more along the lines of how to instantiate a network object, any object, when you need more data than just the position and orientation. For example off the top of my head maybe you need: initial team, initial allegiance, target, do we have lock on target to track target or is there no lock and just dumb fire, etc… I could go on and on about attributes needed at creation time. My dilemma was not knowing how to get the data initialized on all clients, and I thought Network.Initialize was the only option. When I learned I can use an rpc call to send as much data as needed then Initialize the object locally on each client, but associate it to it’s primary network copy, it was exactly what I needed. I hope others will find that solution beneficial too. I’m actually working now on a full Unity3D Networking Tutorial to explain the what and why along with the how to help anyone with no networking experience get started. I hope to have it done within the week.

I realize some might say the remote clients should be dumb and just update the position and orientation from NetworkView and not perform other logic. That is one way to design a network game, but I like more of a hybrid approach. If I hit something on the client but not the parent I don’t want the missile going through the object. I want it to behave appropriately on the client. The real trick is where do you apply damage. I’ll only apply damage on one client, the one I deem the right one. But there is still some local behavior I need to control.