Add component to instantiated gameboject

Options
hello,

i'm using the PhotonNetwork.Instantiate in order to instantiate a game object accross the network. This work fine so far. But, when i'm trying to add a component to this, it adds only localy.
How can i make the other player see this added component?

ennemySpawn = PhotonNetwork.Instantiate(ennemyData.ennemyGO.name, new Vector3(spawnVectorX, spawnVectorY, spawnVectorZ), Quaternion.identity);

creepStats = ennemySpawn.AddComponent<CreepStats>();//attach data to the creep

Comments

  • Tobias
    Options
    Yes, when you locally add components, those won't be synchronized.
    Most networking solutions try to sync as few info as possible. Recreating whatever gets added or removed will end in disaster, so it's not done.

    Add the components you need to the prefab that resembles your networked object. Then, on instantiate, you may enable or disable some.
    In general: Don't mess around with this too much, as it will be hard to analyze when it's buggy.
  • Clevereen
    Options
    Thank you so much for your answer, i've spent soooo much time trying to solve this issue....
    well i'm a bit disapointed that it's not possible however, let's suppose that i add the component before, i still have to synchronize the datas:

    i saw that when we instantiate a game object, it is possible to set data

    object[] myCustomInitData=new object[]
    {
    player.transform.position, player.transform.rotation, photonView.ViewID
    };

    PhotonNetwork.Instantiate("MyPrefabName", new Vector3(0, 0, 0), Quaternion.identity, 0, myCustomInitData);

    the question is :
    can i set scriptable object & other variables to the instantiated object data?
    i want to do something like so :

    object[] myCustomInitData=new object[]
    {
    itemData,
    name
    };


    How can i use the data and ensure that other players see the updated values?
  • Tobias
    Options
    I understood your post wrong and got "I want to change my components frequently". Yes, you can customize the instantiated networked object but you have to do it on all client in a way that sender and receiver fit together. E.g. while the object reacts to input on the controlling client, it will ignore input when it's a remote variant.

    Yes, you can use the CustomInitData. It's meant specifically to customize the instantiated object, too. It's a one time setup, which is fine.

    You don't have to send the viewID and Transform, as that's part of the parameters for PhotonNetwork.Instantiate and gets synced!
  • Clevereen
    Options
    I confirm that I only want to add the component once and for all (one time setup). How can i do to ensure that all client receives the info?

    I've spent nearly 5 days searching everywhere and trying every solution to reach my first solution, which is, instantiate a game object and add a component on it. Before trying the 2nd way, could you help me achieve the first way?

    here are the solution i've tryied :
    • Instantiation through the photonnetwork.instantiate //instantiate and add a component
    • Manual instantiation //local instatiation + add component and synchronize
    • [PunRPC] //=> bug
    • public void OnPhotonInstantiate(PhotonMessageInfo info) //=> not possible as the component script is added after the instantiation

    No solution seems to work as the other client doesn't see the added component. i'm a bit hopeless.
  • Tobias
    Options
    How can i do to ensure that all client receives the info?

    The best way is to do this via the CustomInitData. This is permanently recorded and relates to the View anyways.
    You need some script that is enabled and will be called OnPhotonInstantiate, to add/remove other scripts, which are not part of the instantiation.

    If you need to modify the networked object post-creation, you could use a buffered RPC.
    Meaning: RPC( ... RpcTarget.OthersBuffered, ...)
    This will store the RPC on the server for anyone joining. If nobody else is expected, you can use a normal RPC.
  • Clevereen
    Options
    Thank you very much, after some time, i've finally done what i wanted!

    let me resume the final purpose was:
    1-Instantiate a gameobject accross the network
    2-Add a component with a scriptable object on it and ensure the other players see it


    for those who are interrested, here is the code :
    //EnnemyData.cs => This is my scriptable object that contains my datas
    using UnityEngine;
    public class EnnemyData : ScriptableObject
    {
        public GameObject ennemyGO;
        public Transform target;
    
        //ACCROSS THE NETWORK
        public byte Id { get; set; }
    }
    
    //MyGroundPlayer.cs => the script that has the photonview component
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using Photon.Pun;
    public class MyGroundPlayer : MonoBehaviourPun, IPunObservable
    {
        /*---------------------------------------------------------------------------------------------*/
        /*           ADD A COMPONENT ACCROSS THE NETWORK
        /*--------------------------------------------------------------------------------------------*/
    
        //called by Spawn.cs
        [PunRPC] 
        public void RPC_SpawnOnNetwork(int ennemyPhotonView_i, EnnemyData ennemyData_i)
        {
            Debug.Log("The RPC_SpawnNetwork is receiving :" + ennemyPhotonView_i, ennemyData_i);
            CreepStats creepStats= PhotonView.Find(ennemyPhotonView_i).gameObject.AddComponent<CreepStats>();
            creepStats.ennemyData = ennemyData_i; //pass the value
            creepStats.parent = this.gameObject;//pass the value
            creepStats.useNetwork = true;
        }
    }
    
    
    //Spawn.cs : => The script that allows to instantiated a game object with custom parameters
    using Photon.Pun;
    using ExitGames.Client.Photon;
    public class Spawn : MonoBehaviourPun
    {
    [SerializeField] PhotonView thePhotonView;
    
        private void Awake()
        {
            if (useNetwork)
            {
                //Photon doesn't recognize by default custom class, so we need to register it
                PhotonPeer.RegisterType(typeof(EnnemyData), (byte)'A', SerializeEnnemyData, DeserializeEnnemyData);
            }
    
        }
    
    private void InstantGO()
    {
                    //Instantiate accross the network (never use PUN RPC to spawn)
                    ennemySpawn = PhotonNetwork.Instantiate(ennemyData.ennemyGO.name, new Vector3(spawnVectorX, spawnVectorY, spawnVectorZ), Quaternion.identity);
                    //Get the photonView of the instantiated GameObject in order to pass it as a parameter
                    ennemyPhotonView = ennemySpawn.GetPhotonView().ViewID;
    
                    //Call the RPC of MyGroundPlayer.cs to add the component post-instantiation
                    thePhotonView.RPC("RPC_SpawnOnNetwork", RpcTarget.AllBuffered,ennemyPhotonView, ennemyData);
    }
        /*---------------------------------------------------------------------------------------------*/
        /*                                    ACCROSS THE NETWORK
        /*--------------------------------------------------------------------------------------------*/
    
        #region Serialize/Deserialize a class
        /// <summary>
        /// IN ORDER TO PASS A SCRIPTABLE OBJECT WITH PUN RPC, WE NEED TO SERIALIZE IT AS PHOTON
        /// DOESN'T RECOGNIZE IT BY DEFAULT CUSTOM CLASS
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
    
        public static object DeserializeEnnemyData(byte[] data)
        {
            //var result = new EnnemyData();//for monobehaviour
            var result = ScriptableObject.CreateInstance<EnnemyData>();//Scriptable Object
            result.Id = data[0];
            return result;
        }
    
        public static byte[] SerializeEnnemyData(object ennemyData)
        {
            var c = (EnnemyData)ennemyData;
            return new byte[] 
            {
                c.Id
            };
        }
        #endregion
    }
    

    Again Tobias, i'm really greatfull!