0
votes

I am using Photon PUN for multiplayer and instantiating GameObjects (OtherCraft) from a prefab as players enter, and destroying them as they leave - or rather, the destroy doesn't work. The relevant code is as follows:

The prefab is loaded in Start(), and there is a dictionary to hold references to the instantiations as they happen (Other craft is simply a cube with mesh and script right now):

    OtherCraft
            otherCraftPrefab;

    Dictionary<int, OtherCraft>
            otherCrafts = new Dictionary<int, OtherCraft>();
    
    ....  //  the following in Start()

    GameObject
            tmp = (GameObject)Resources.Load("Prefabs/OtherCraft", typeof(GameObject));
    otherCraftPrefab = null;


    if (tmp == null)
        Debug.Log("Failed to load prefab for other craft");

    else
        otherCraftPrefab = tmp.GetComponent<OtherCraft>();

When a new entrant is a notified by an OnPlayerEnteredRoom(Player newPlayer), a new craft is created and added to the dictionary:

    OtherCraft
            otherCraft = Instantiate(otherCraftPrefab, new Vector3(0,1,0), Quaternion.identity);

    otherCraft.setActorNumber(newPlayer.ActorNumber);
    otherCraft.setNickName(newPlayer.NickName);

    otherCrafts.Add(newPlayer.ActorNumber, otherCraft);
    Debug.Log("Other craft instantiated - " + otherCraft.getNickName() + ", ActorNumber=" + otherCraft.getActorNumber());

The Debug.Log line shows it was all OK (Created craft - OtherCraft(Clone) (OtherCraft): nick2, ActorNumber=2), the right ActorNumber etc, and it shows up in the game view and hierachy OK.

When notified of player leaving by OnPlayerLeftRoom(Player exPlayer), it references the entry in the dictionary and gets rid of it again:

    OtherCraft
            otherCraft = otherCrafts[exPlayer.ActorNumber];
    int     actorNumber = otherCraft.getActorNumber();
    string  nickName = otherCraft.getNickName();
    Debug.Log("Recovered craft - " + otherCraft.ToString() + ": " + nickName + ", ActorNumber=" + actorNumber);

    otherCrafts.Remove(actorNumber);
    Destroy(otherCraft);

Except it doesn't, it is still there in the game view and hierachy. The Debug.Log line also shows wrong information (Recovered craft - OtherCraft(Clone) (OtherCraft): , ActorNumber=0). It got the wrong thing back from the dictionary.

Cannot see what I have done wrong?

1
did you add a log if the exPlayer.ActorNumber is correct (should be 2 right?) Also the nickname seems to be empty ...derHugo
Thanks, yes, there was another debug line above which proved that, I just didn't include it. Empty nickname is the default. Actually I have solved it, see answer added.nmw01223

1 Answers

1
votes

Think I have solved this. The GameObject - OtherCraft - has a script, also named OtherCraft. What actually got stored in the dictionary (and later removed and destroyed) was the instance of the script, not the GameObject.

It is kind of implied in a lot of the Unity community instructional docs, videos etc to keep the names the same - "create a GameObject 'Fred', now add a script to it, named - why not - 'Fred'". Well, that way can lie trouble. A lot of the time the two are interchangeable and you want access to the script anyway. They are nearly interchangeable, but it seems, not always. Not in this case anyway.

I changed it so the GameObject was OtherCraftGo, keeping the script as OtherCraft. The dictionary was changed to store GameObjects, and when needed, the script was accessed by OtherCraft script = myOtherCraftGo.GetComponent<OtherCraft>().

Solved the problem. A salutory lesson, for me, anyway.