Stop hitting yourself.

Options
Hi There,

I was just wondering how I make my player hit the other players, but not himself, if his weapon is hitting his collider.

Thanks!

Comments

  • Malace
    Options
    Two ways to do this. Both not really pun related. But all the same.
    1. Set up two physics layers. Player and Enemy. Set them to not interact with themselves.(project settings>physics). When the players join they should assign their collider to the player layer. And all other hit box/weapons to the enemy layer. (this is lowest overhead on performance as the collision is completely ignored)
    2. Do a check in your collision to see if the collision was your players hit box or an enemy's. If your weapon is a child or grandchild you could get component your way to store it in a variable at start. if so do nothing. Else apply damage.(this is where code can bog down every collision call)

    I can't get much more specific without knowing more on scene setup. I assume these aren't bullets you could spawn out in front of your hit box?
  • ChimeraBlack
    Options
    Hi Thanks!

    Yeah that sounds about right. and no, the action is "Swinging a sword in a cleaving motion."

    the way I'm detecting collision is with physics.OverlapSphere. I then loop through any colliders found and if the collider is tagger "Player" it deals damage. I was trying to put something like :

    If(isMine)
    {
    return;
    }

    At the top of the damage taking method. Problem is that doesn't seem to have any effect whatsoever.

    I follow you on your above example, but I can't visualize how I would instantiate a player, and have it re-classify the colliders for everyone else. I thought a local player cannot affect other players.

    How can I instantiate a player on the player layer, that tells all the other players it's on the enemy layer?
  • Malace
    Malace
    edited April 2019
    Options
    Think of it like this. Each client has its own Scene and own copy of everything in it. When a player joins the prefab is created as many times as you have players. Player one creates a copy of the enemy and then sync's it with the server. So he can on his side tag that object as a enemy by using photonView.IsMine.
    Unless you RPC/Event/or Stream this change it is local only. So each client can deviate on what object is an enemy or not.

    It must be in a pun mono class so your player controller script should work fine if its on the base object with the collider for the player hit box.
    Just add the following to either Awake() or Start() of your player prefab. you will want to target the object with the collider for the player. So if for some reason that isn't on the base object alter the this.gameObject to a inspector set public gameobject variable and use that.Tag="tagname"

    **Edit --
    One thing I thought of after posting my additional suggestion below. You will need to account for players as they join the game. Each player already in the game will need to update the new player as enemy, as such my code here needs to be put somewhere that runs anytime a client joins. Which gets a little convoluted. For simplicity you could place this within the players RefreshInstance() method. But that's a dirty solution. Instead you should set a bool to true in OnPlayerEnteredRoom(). Which is likely in another script. But the gist is.. We should only run this code on each client refresh if a new player has joined. And set it to false after we have updated all the tags. --**
        
       if (!photonView.IsMine)
        {
            this.gameObject.Tag = "Enemy";//**NOTE: this may need to be more specific. If you have NPC's they too would have a view that may not be this clients. Which would not always make them an enemy.
        }
         else
        {
           this.gameObject.Tag = "Player";//will only set the tag for the client running the code.
         }
  • Malace
    Options
    Also I'd like to make the following suggestion for collisions. It may make things easier to see and also simplify your hit detection.
    - I am just guessing on how you currently doing things.

    I would use a mesh collider. Even with Primitive shapes. This will give you better hit box detection and allow you to migrate to advanced models down the road. No matter the shape your object will still have a mesh that the collider can mimic. So your sword should not detect a hit until its model enters another collider.

    This is done best by using the OnCollisionEnter() method. Place a script on your weapon with the attached code below for example.

    This function will fire every time the collider enters another collider. You can simply check if the object that we entered is tagged enemy.
    //Place script on any Object with a Collider to see when it enters another collider in the scene.
    public class ExampleClass : MonoBehaviour
    {
    
        void OnCollisionEnter(Collision collision)
        {		
    		//here is where you would check if(collision.gameObject.Tag == "Enemy"){dostuff();} 
    		//this is a great snippit to see exactly what collisions occur through this method.
            foreach (ContactPoint contact in collision.contacts)
            {
                Debug.DrawRay(contact.point, contact.normal, Color.white);			
            }
    
        }
    }