Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third Party Difficulty Assigning Parent to Photon Object

Discussion in 'Multiplayer' started by Mashimaro7, Jul 15, 2021.

  1. Mashimaro7

    Mashimaro7

    Joined:
    Apr 10, 2020
    Posts:
    727
    I'm still fairly new to Photon, or online in general, I'm having a lot of difficulty assigning a child to the proper object. I'm using the Ready Player Me plugin(honestly, I hate it lol, but my client wants it so) It instantiates the object in the scene and uses a callback to get a reference to it, as far as I can tell there's no easy way to PhotonNetwork.Instantiate with it.

    I'm having difficulty assigning the object to the child of the player object I have. It works just fine on one player, what I'm doing is spawning the player in with

    -PhotonNetwork.Instantiate in the callback(after checking if the player already exists).
    -Assigning a name with the local player's actor number if this is a new object(as a round about way to not assign to someone else's object)

    -Using a method in the player's movement script to call an RPC, which is attached to the player's camera, that is called directly after spawn which searches the scene for this name, takes all the parts of this object, puts them in the holder's uh, holder(used to contain a model, now it's empty except for an armature)

    -Reassigning the animator so it doesn't get confused, etc.

    So, it seems to not be assigning the name properly to the second player, I'm guessing the values don't sync accross photon objects in different platforms?

    Here's my spawn script.

    Code (csharp):
    1.  
    2. [code=CSharp]using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using Photon.Pun;
    6. using Photon.Realtime;
    7. using UnityEngine.SceneManagement;
    8. using UnityEngine.Video;
    9. using Wolf3D.ReadyPlayerMe.AvatarSDK;
    10.  
    11. public class GManager : MonoBehaviourPunCallbacks
    12. {
    13.  
    14.     Dictionary<int, GameObject> spawnedPlayers;
    15.     [SerializeField] GameObject testPlayer;
    16.     [SerializeField] GameObject[] avatars;
    17.     PhotonView view;
    18.     [SerializeField]Transform spawnPoint;
    19.  
    20.     List<PlayerData> playerInfos;
    21.     GameObject playersAvatar;
    22.  
    23.     TextManager thisText;
    24.  
    25.     VideoPlayer[] video;
    26.     float timer = 1,timerSet = 5;
    27.     bool videoPlaying;
    28.     [SerializeField] string[] playerObject;
    29.     GameObject lastPlayer;
    30.  
    31.  
    32.     void Awake()
    33.     {
    34.  
    35.         spawnedPlayers = new Dictionary<int, GameObject>();
    36.         if (Application.platform == RuntimePlatform.Android)
    37.         {
    38.             VrModeController vr = gameObject.AddComponent<VrModeController>();
    39.             vr.EnterVR();
    40.         }
    41.         video = FindObjectsOfType<VideoPlayer>();
    42.         for (int i = 0; i < video.Length; i++)
    43.         {
    44.             video[i].Play();
    45.         }
    46.      
    47.  
    48.         view = GetComponent<PhotonView>();
    49.         SpawnPlayer(PhotonNetwork.LocalPlayer.ActorNumber,ThisPlayerData.thisData.playerName,ThisPlayerData.thisData.playerDescription);
    50.  
    51.     }
    52.  
    53.     private void Start()
    54.     {
    55.         StartCoroutine(Delay());
    56.     }
    57.     IEnumerator Delay()
    58.     {
    59.         yield return new WaitForSeconds(0.1f);
    60.         PlayerAssigner[] assigners = FindObjectsOfType<PlayerAssigner>();
    61.         Identifier[] identifiers = FindObjectsOfType<Identifier>();
    62.         for (int i = 0; i < assigners.Length; i++)
    63.         {
    64.  
    65.             identifiers[i].transform.parent = assigners[i].transform;
    66.         }
    67.  
    68.         view.RPC("SpawnAvatar", RpcTarget.All, ThisPlayerData.thisData.playerModelName);
    69.     }
    70.  
    71.     private void Update()
    72.     {
    73.         if(timer >= 0)
    74.         {
    75.             timer -= Time.deltaTime;
    76.         }
    77.         else
    78.         {
    79.             timer = timerSet;
    80.             view.RPC("GetMasterVideo", RpcTarget.MasterClient);
    81.             videoPlaying = true;if (video.Length > 0)
    82.             {
    83.                 for (int i = 0; i < video.Length; i++)
    84.                 {
    85.                     if (!video[i].isPlaying) video[i].Play();
    86.                 }
    87.             }
    88.         }
    89.     }
    90.  
    91.     [PunRPC]
    92.     void SpawnPlayer(int id, string name, string desc)
    93.     {
    94.         if (SceneManager.GetActiveScene().name == "DemoScene")
    95.         {
    96.  
    97.         }
    98.     }
    99.  
    100.     [PunRPC]
    101.     void SpawnAvatar(string url)
    102.     {
    103.         AvatarUri aUrl = new AvatarUri();
    104.    
    105.         AvatarLoader loader = new AvatarLoader();
    106.         loader.LoadAvatar(url, OnAvatarLoaded);
    107.     }
    108.  
    109.     private void OnAvatarLoaded(GameObject avatar, AvatarMetaData metaData)
    110.     {
    111.  
    112.         GameObject p = null;
    113.         //  if (playersAvatar == null) return;
    114.         if (spawnedPlayers.ContainsKey(PhotonNetwork.LocalPlayer.ActorNumber)) p = spawnedPlayers[PhotonNetwork.LocalPlayer.ActorNumber];//p = spawnedPlayers[PhotonNetwork.LocalPlayer.ActorNumber];
    115.         else
    116.         {
    117.             p = PhotonNetwork.Instantiate(playerObject[0], spawnPoint.position + new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)), Quaternion.identity);
    118.             p.GetComponent<AvatarIdentifier>().iD = PhotonNetwork.LocalPlayer.ActorNumber * 10;
    119.         }
    120.  
    121.         avatar.AddComponent<AvatarIdentifier>().iD = p.GetComponent<AvatarIdentifier>().iD;
    122.         avatar.name += avatar.GetComponent<AvatarIdentifier>().iD;
    123.  
    124.         // GameObject p = PhotonNetwork.Instantiate(testPlayer.name, Vector3.zero, Quaternion.identity);
    125.         if (ThisPlayerData.thisData.playerModelName != "")
    126.         {
    127.             // AvatarLoader loader = new AvatarLoader();
    128.             // loader.LoadAvatar(ThisPlayerData.thisData.playerModelName);
    129.  
    130.             // GameObject t = Instantiate(ThisPlayerData.thisData.playerModel, spawnPoint.position + new Vector3(Random.Range(-1f, 1f), 0, Random.Range(-1f, 1f)), Quaternion.identity,p.transform);
    131.         }
    132.         if (view.IsMine)
    133.         {
    134.             p.tag = "ThisPlayer";
    135.             p.transform.GetComponentInChildren<PlayerMovement>().tag = "ThisPlayer";
    136.             avatar.tag = "ThisPlayer";
    137.         }
    138.         PlayerData d = new PlayerData(ThisPlayerData.thisData.playerDescription, ThisPlayerData.thisData.playerName, "");
    139.  
    140.         thisText = p.GetComponentInChildren<TextManager>();
    141.         lastPlayer = p;
    142.      
    143.         //avatar.transform.parent = p.transform;
    144.  
    145.         if (lastPlayer)avatar.transform.parent = lastPlayer.transform;
    146.         avatar.transform.localPosition = Vector3.zero;
    147.        // p.GetComponentInChildren<PlayerMovement>().newModel = avatar.transform;
    148.         p.GetComponentInChildren<PlayerMovement>().AssignNewPlayer();
    149.         view.RPC("AssignTexts", RpcTarget.All);
    150.         spawnedPlayers.Add(PhotonNetwork.LocalPlayer.ActorNumber, p);
    151.     }
    152.  
    153.     [PunRPC]
    154.     void AssignTexts()
    155.     {
    156.         thisText.SetTexts();
    157.     }
    158.  
    159.  
    160.  
    161.     [PunRPC]
    162.     void GetMasterVideo()
    163.     {
    164.         for (int i = 0; i < video.Length; i++)
    165.         {
    166.             view.RPC("SyncVideos", RpcTarget.Others, video[i].frame,i);
    167.         }
    168.     }
    169.  
    170.     [PunRPC]
    171.     void SyncVideos(long videoDuration, int index)
    172.     {
    173.         if(Mathf.Abs(video[index].frame - videoDuration) > 30) video[index].frame = videoDuration;
    174.         video[index].Play();
    175.     }
    176.  
    177. }
    178.  
    179.  
    And here's my Camera's script, the one used for assigning the object.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Google.XR.Cardboard;
    5. using Photon.Pun;
    6.  
    7. public class PlayerMovement : MonoBehaviour
    8. {
    9.     Camera cam;
    10.     public Transform model,newModel, armatureHips;
    11.     Transform holder,cameraAnchor;
    12.  
    13.     Vector3 playerOffset;
    14.     [SerializeField] Vector3 sittingOffset;
    15.     Vector3 preSitPos, preSitParentPos, cameraAnchorPos;
    16.  
    17.     [SerializeField] float targetSpeed, toggleAngle = 30, sitSpeed, smoothSpeed = 1;
    18.     float speedGoal, speed, defaultY;
    19.     CharacterController controller;
    20.     [SerializeField] float camMaxX, camMinX;
    21.  
    22.     [SerializeField] GameObject emoteUI,playerUI;
    23.  
    24.     [SerializeField]PlayerScriptable scriptable;
    25.  
    26.     public PlayerEmotions emotes;
    27.  
    28.     [HideInInspector]public Animator anim;
    29.  
    30.     public Transform chair;
    31.     public float timerToStand,timerToTalk;
    32.     float animationSpeedGoal, animationSmoothSpeed;
    33.  
    34.     public bool sitting,standing,canWalk;
    35.     PhotonView view;
    36.  
    37.     [SerializeField]float yPos = 1.7f;
    38.  
    39.     RaycastHit hit;
    40.  
    41.     public PlayerData info;
    42.  
    43.     [SerializeField]LayerMask rayLayerToIgnore;
    44.  
    45.     [SerializeField] TextManager nameTag;
    46.  
    47.     [SerializeField] Vector3 cameraOffset;
    48.  
    49.     bool talking;
    50.     Rigidbody rb;
    51.  
    52.     // Start is called before the first frame update
    53.     void Start()
    54.     {
    55.      
    56.         SetDependencies();
    57.         emoteUI.SetActive(false);
    58.      
    59.     }
    60.  
    61.     private void SetDependencies()
    62.     {
    63.         rb = GetComponentInParent<Rigidbody>();
    64.         cameraAnchor = transform.parent.transform.Find("CameraAnchor");
    65.         view = GetComponent<PhotonView>();
    66.         cam = GetComponent<Camera>();
    67.  
    68.         if (!view.IsMine)
    69.         {
    70.             cam.enabled = false;
    71.             Destroy(GetComponent<AudioListener>());
    72.             playerUI.SetActive(false);
    73.         }
    74.         else
    75.         {
    76.             tag = "ThisPlayer";
    77.         }
    78.  
    79.         emoteUI = transform.parent.transform.Find("PlayerUI").gameObject;
    80.  
    81.         holder = transform.parent;
    82.         controller = holder.GetComponent<CharacterController>();
    83.  
    84.         StartCoroutine(Delay());
    85.     }
    86.  
    87.     IEnumerator Delay()
    88.     {
    89.  
    90.         yield return new WaitForSeconds(0.1f);
    91.  
    92.  
    93.  
    94.     }
    95.  
    96.     private void Update()
    97.     {
    98.         if (anim != null) anim.SetFloat("Speed", animationSmoothSpeed);
    99.         if (timerToStand > 0)
    100.         {
    101.             timerToStand -= Time.deltaTime;
    102.         }
    103.         else if(sitting && standing)
    104.         {
    105.             sitting = false;
    106.        
    107.             chair = null;
    108.  
    109.             anim.SetBool("Standing", false);
    110.         }
    111.      
    112.         if(timerToTalk > 0)
    113.         {
    114.             timerToTalk -= Time.deltaTime;
    115.         }
    116.         else if (talking)
    117.         {
    118.             talking = false;
    119.          
    120.             anim.SetBool("Talking", talking);
    121.         }
    122.  
    123.     }
    124.  
    125.     // Update is called once per frame
    126.     void FixedUpdate()
    127.     {
    128.         if (armatureHips)
    129.         {
    130.             if (armatureHips.parent.localPosition.y < -0.1) armatureHips.parent.localPosition = Vector3.zero;
    131.             if (armatureHips.parent.localEulerAngles != Vector3.zero) armatureHips.parent.localEulerAngles = new Vector3(armatureHips.parent.eulerAngles.x, 0, armatureHips.parent.eulerAngles.z) ;
    132.         }
    133.         if (Mathf.Abs(Vector3.Dot(transform.forward, Vector3.down)) > toggleAngle && !sitting && canWalk)
    134.         {
    135.  
    136.             if (view.IsMine) MovePlayer();
    137.  
    138.         }
    139.         else
    140.         {
    141.             animationSpeedGoal = 0;
    142.             speedGoal = 0;
    143.         }
    144.         if (animationSmoothSpeed != animationSpeedGoal)
    145.         {
    146.             animationSmoothSpeed = Mathf.Lerp(animationSmoothSpeed, animationSpeedGoal, 3 * Time.deltaTime);
    147.         }
    148.  
    149.  
    150.         if (!sitting)
    151.         {
    152.             if (model)
    153.             {
    154.                 model.transform.localPosition = Vector3.zero;
    155.                 if (view.IsMine) model.localEulerAngles = Vector3.zero;
    156.             }
    157.             if (view.IsMine)
    158.             {
    159.                 RotatePlayer();
    160.  
    161.             }
    162.             if (chair != null)
    163.             {
    164.                 chair.gameObject.SetActive(false);
    165.             }
    166.         }
    167.  
    168.         transform.position = cameraAnchor.position;
    169.  
    170.         /* if(Application.platform == RuntimePlatform.WindowsEditor)
    171.          {
    172.              float mouseY = Input.GetAxis("Mouse Y");
    173.              float mouseX = Input.GetAxis("Mouse X");
    174.  
    175.              rotX -= mouseY;
    176.  
    177.              rotX = Mathf.Clamp(rotX, -85f, 85f);
    178.              //rotX *= Time.deltaTime * mouseSens;
    179.              transform.localEulerAngles = new Vector3(rotX, transform.localEulerAngles.y, transform.localEulerAngles.z);
    180.              transform.Rotate(Vector3.up * mouseX);
    181.          }*/
    182.     }
    183.  
    184.     void RotatePlayer()
    185.     {
    186.         if(model != null)model.rotation = Quaternion.Euler(new Vector3(holder.eulerAngles.x, transform.eulerAngles.y, holder.eulerAngles.z));
    187.         if(model != null)model.localEulerAngles = new Vector3(model.localEulerAngles.x, transform.localEulerAngles.y, model.localEulerAngles.z);
    188.     }
    189.  
    190.     void MovePlayer()
    191.     {
    192.         if (talking)
    193.         {
    194.          
    195.             talking = false;
    196.             anim.SetBool("Talking", talking);
    197.             timerToTalk = 0;
    198.         }
    199.         speed = Mathf.Lerp(speed, speedGoal, smoothSpeed * Time.deltaTime);
    200.  
    201.         Vector3 direction = new Vector3(transform.forward.x, .1f, transform.forward.z).normalized;
    202.         rb.MovePosition(rb.position + (direction * speed * Time.deltaTime));
    203.  
    204.  
    205.         speedGoal = targetSpeed;
    206.         animationSpeedGoal = 1;
    207.  
    208.     }
    209.  
    210.     public void AssignNewPlayer()
    211.     {
    212.         if (!view) view = GetComponent<PhotonView>();
    213.  
    214.         StartCoroutine(DelayAssign());
    215.     }
    216.  
    217.     IEnumerator DelayAssign()
    218.     {
    219.         yield return null;
    220.  
    221.         view.RPC("AssignNewPlayerRPC",RpcTarget.All);
    222.     }
    223.  
    224.     [PunRPC]
    225.     void AssignNewPlayerRPC()
    226.     {
    227.  
    228.         model = transform.parent.GetComponentInChildren<Identifier>().transform;
    229.         anim = holder.GetComponentInChildren<Animator>();
    230.         anim.runtimeAnimatorController = scriptable.animationController;
    231.  
    232.         emotes = model.GetComponentInChildren<PlayerEmotions>();
    233.  
    234.         playerOffset = model.localPosition;
    235.  
    236.         AvatarIdentifier[] identifiers = FindObjectsOfType<AvatarIdentifier>();
    237.  
    238.         for (int i = 0; i < identifiers.Length; i++)
    239.         {
    240.             if (identifiers[i].iD == holder.GetComponent<AvatarIdentifier>().iD && identifiers[i].gameObject.name == "Avatar" + holder.GetComponent<AvatarIdentifier>().iD)
    241.             {
    242.                 newModel = identifiers[i].transform;
    243.             }
    244.         }
    245.         newModel.parent = holder;
    246.         newModel.localPosition = Vector3.zero;
    247.  
    248.  
    249.         Transform[] modelChildren = new Transform[newModel.childCount];
    250.         anim = model.GetComponent<Animator>();
    251.         //Avatar av = anim.avatar;
    252.         for (int i = 0; i < modelChildren.Length; i++)
    253.         {
    254.             modelChildren[i] = newModel.GetChild(i);
    255.  
    256.         }
    257.         for (int i = 0; i < modelChildren.Length; i++)
    258.         {
    259.  
    260.             if (modelChildren[i].name == "Armature")
    261.             {
    262.                 armatureHips = model.Find("Armature");
    263.                 Destroy(armatureHips.gameObject);
    264.                 armatureHips = modelChildren[i].Find("Hips");
    265.              
    266.              
    267.             }
    268.             modelChildren[i].parent = model;
    269.         }
    270.  
    271.         for (int i = 0; i < modelChildren.Length; i++)
    272.         {
    273.             if (modelChildren[i].GetComponent<SkinnedMeshRenderer>()) modelChildren[i].GetComponent<SkinnedMeshRenderer>().rootBone = armatureHips;
    274.         }
    275.  
    276.         //armature.transform.localPosition = Vector3.zero;
    277.  
    278.         Destroy(newModel.gameObject);
    279.  
    280.         cameraAnchor.parent = armatureHips.Find("Spine").Find("Spine1").Find("Spine2").Find("Neck");
    281.         cameraAnchor.localPosition = cameraOffset;
    282.  
    283.         cameraAnchorPos = cameraAnchor.localPosition;
    284.         StartCoroutine(AnimDelay());
    285.         //newModel.GetComponent<Animator>().runtimeAnimatorController = scriptable.animationController;
    286.  
    287.  
    288.         /*
    289.         armature.gameObject.SetActive(false);
    290.         newModel = holder.Find("Avatar");
    291.  
    292.  
    293.         newModel.GetComponent<Animator>().runtimeAnimatorController = scriptable.animationController;
    294.         //Destroy(armature.gameObject);
    295.         armature = newModel.Find("Armature");
    296.         anim = newModel.GetComponent<Animator>();*/
    297.  
    298.     }
    299.  
    300.     IEnumerator AnimDelay()
    301.     {
    302.         yield return null;
    303.         anim.Rebind();
    304.     }
    305.  
    306. }
    307.  
    I know it's sloppy, I've been working for a good 30 hours on this and cannot for the life of me figure out how to get this to work. It'd be convenient if the plugin allowed me to just use PhotonNetwork.Instantiate, but it doesn't.

    So, is there an easy way to get a reference to a specific photon object? As the object can't be spawned over the network(or, i don't know how to) I need to spawn each object on load, and assign them. What happens is each player's own avatar seems to be spawning in just fine, but there seems to be an issue with the other player, I'm getting an error saying the "newModel"(in the playerMovement script) is not set to a reference of an object, so I'm guessing it can't find the name?

    Few more points, probably not important, but it's a VR game and it's for mobile. I use the Ready Player Me's Webview to spawn a new avatar, and in the GManager script it's passing in the URL to download the avatar(I don't think the issue is with downloading the avatar though, I have been able to see the other player's model before, just never assign it as a child)

    Sorry for my long post and sloppy code! Can anyone help me out please? Thanks in advance.
     
    Last edited: Jul 15, 2021