2
\$\begingroup\$

I am using Unity3D and I have a problem. I have a script which instantiates the player gameobject once you are connected to the server. I also have an attack script. When there is only 1 player on, everything works fine. When the second player comes on, the attack doesn't work! I did Debug.Log and I found out that when you clicked the other player to attack instead of attacking him, you are attacking the terrain below it.

Here is my code. Instantiate Code:

GameObject myPlayer = PhotonNetwork.Instantiate (
  character, 
  mySpawn.transform.position, 
  mySpawn.transform.rotation, 0) as GameObject;

Attack code:

using UnityEngine;
using System.Collections;

public class SendAttackInfo : Photon.MonoBehaviour
{
  public float damage = 100;

  // Use this for initialization
  void Start()
  {
  }

  void Update()
  {
    bool RMB = Input.GetMouseButtonDown(0);
    if (RMB)
    {
      RaycastHit hit;
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      if (Physics.Raycast(ray, out hit, 100))
      {
        Debug.Log("We arm-hit: " + hit.collider.name);

        hit.collider.transform.gameObject.GetComponent<PhotonView>().RPC(
          "ApplyDamage", 
          PhotonTargets.AllBuffered, 
          damage);
        hit.collider.transform.FindChild("Cube").GetComponent<PhotonView>().RPC(
          "ApplyDamage", 
          PhotonTargets.AllBuffered, 
          damage);
      }
    }
  }
}
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

There are a lot of unknown things to me here.

1) Is your SendAttackInfo script on both players after they spawn in? If so, you will be firing for both you and your opponent when you click since update runs on each player. Take a look at the isMine variable on Photon.Monobehaviour. It will help you write logic that will only be run for the local player.

2) What are you trying to do by searching for “cube” and calling an rpc on that after already calling the rpc on your hit target? This seems likely to be a cause of unexpected behaviour. I could also just not understand your requirements.

3) The fact that things go wrong when the second player joins is telling to me. I would look through all your scripts on the player prefab and analyze each line of code and ask yourself “do I want to run this for everyone or just the player controlling it locally?”. Also keep in mind that the ids on the PhotonViews are very important. If you somehow save a prefab with a non negative instantiation id on it’s PhotonView then photon will not dynamically assign an id at runtime and use the given id instead.

For example: if you create a prefab with a PhotonView on it and save it with view id 5 it will spawn correctly the first time photon.instantiate is called because only one view exists with id 5. Now your buddy joins and spawns a copy of the same prefab. Now there are two views with id 5 on the field. If, for example, you decided to send an rpc to a view with id 5 then you are asking photon to send the data over the network and when each client receives the data they lookup a view with id 5.... how do you think that will work when two of them exist?

The rule with photon views is as follows:

  • if the photon view is saved into a scene it must have a unique id (photon handles guaranteeing the id is unique when you save).

  • if the view will be spawned at runtime it must have an instantiationId of -1. Note that instantiation id and view id are two separate fields on the photon view. This gets tricky whenever you have a prefab with instantiation Id -1 that you drag and drop into a scene to edit because photon will then give it a new view and instantiation id that is not -1. This will now be saved to your prefab and will cause all sorts of issues when spawning it at runtime. You can force photon to save the proper values by not having the prefab in the scene and saving the project.

I am not near a computer at the moment to double check everything so feel free to ask questions if you have any.

I just wanted to share what I know since I have encountered these issues before. Good luck!

\$\endgroup\$
0
\$\begingroup\$

It sounds like you need to apply a LayerMask to your Raycast call. To do this you need to assign a different layer to your enemy object in the inspector, then in the code do something like this:

public class SendAttackInfo : Photon.MonoBehaviour
{
  public float damage = 100;
  private LayerMask enemyLayerMask = LayerMask.GetMask("MyLayerName");

  void Update()
  {
    bool RMB = Input.GetMouseButtonDown(0);
    if (RMB)
    {
      RaycastHit hit;
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      if (Physics.Raycast(ray, out hit, 100, enemyLayerMask.value))
      {
        Debug.Log("We arm-hit: " + hit.collider.name);

        hit.collider.transform.gameObject.GetComponent<PhotonView>().RPC(
          "ApplyDamage", 
          PhotonTargets.AllBuffered, 
          damage);
        hit.collider.transform.FindChild("Cube").GetComponent<PhotonView>().RPC(
          "ApplyDamage", 
          PhotonTargets.AllBuffered, 
          damage);
      }
    }
  }
}

The layermask variable is given the name of the layer you created and assigned to the enemy and it's value is used in your raycast so that the cast only looks for hits with the matching layer. Alternately you can expose the layermask variable publicly and the inspector will provide a dropdown where you can pick one or more layers you want to be eligible for the hit.

\$\endgroup\$
1
  • \$\begingroup\$ @geotsak It should work, you are doing something wrong. \$\endgroup\$ Commented May 16, 2016 at 17:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .