question

omerdruu avatar image
omerdruu asked

Entity Files, Load User Profile Picture

Hello, I am developing a project in unity and photon and playfab are integrated into my project. In the login (registration phase), I make users choose 1 profile photo and upload it to the playfab entity files. Since I want users to be able to see the picture of other users in the room when they set up a room, I am trying to download the profile photo selected by the user at login from the playfab entity file. I have a prefab showing the users in the room and the code file is in this prefab

public class playerprafab : MonoBehaviourPunCallbacks
{
 

    [SerializeField]
    private Text _text;
    [SerializeField]
    private Image profilep2;
    public bool Ready = false;
    public Player Player { get; private set; }


    public int GlobalFileLock = 0;
    private string entityId; // Id representing the logged in player
      private string entityType; // entityType representing the logged in player
    private readonly Dictionary<string, string> _entityFileJson = new Dictionary<string, string>();






    public void SetPlayerInfo(Player player)
    {
        Player = player;
        _text.text = player.NickName;
 
        
    }


    void OnSharedFailure(PlayFabError error)
    {
        Debug.LogError(error.GenerateErrorReport());
        GlobalFileLock -= 1;
    }


    void OnLogin(LoginResult result)
    {


        entityId = result.EntityToken.Entity.Id;
        // The expected entity type is title_player_account.
        entityType = result.EntityToken.Entity.Type;
        Debug.Log(entityType + entityId);
    }


    public void LoadAllFiles()
    {
        if (GlobalFileLock != 0)
            throw new Exception("This example overly restricts file operations for safety. Careful consideration must be made when doing multiple file operations in parallel to avoid conflict.");


        GlobalFileLock += 1; // Start GetFiles
        var request = new PlayFab.DataModels.GetFilesRequest { Entity = new PlayFab.DataModels.EntityKey { Id = entityId, Type = entityType } };
        PlayFabDataAPI.GetFiles(request, OnGetFileMeta, OnSharedFailure);
    }




 
        void Start()
    {

   

        PlayFabAuthenticationAPI.GetEntityToken(new GetEntityTokenRequest(),
	(entityResult) =>
	{
	var entityId = entityResult.Entity.Id;
	var entityType = entityResult.Entity.Type;
	}, OnPlayFabError);
   	
     LoadAllFiles();
 }




    void OnGetFileMeta(PlayFab.DataModels.GetFilesResponse result)
    {
        Debug.Log("Loading " + result.Metadata.Count + " files");


        _entityFileJson.Clear();
        foreach (var eachFilePair in result.Metadata)
        {
            _entityFileJson.Add(eachFilePair.Key, null);
            GetActualFile(eachFilePair.Value);
        }
        GlobalFileLock -= 1; // Finish GetFiles
    }


    void GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)
    {
        GlobalFileLock += 1; // Start Each SimpleGetCall
        PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
            result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock -= 1; }, // Finish Each SimpleGetCall
            error => { Debug.Log(error); }
        );
    }


    void OnPlayFabError(PlayFabError error)
    {
        Debug.Log(error.GenerateErrorReport());
    }

}


Result : I can't access Entity Key .

/File/GetFiles: Invalid input parameters EntityKey: Type or TypeString is required. EntityKey: Id is required. EntityKey: is not an allowed value of Type.

This prefab is loaded after login, when the user joins or sets up the room. I'm already logged in, why can't I access the entity key.

Question I want to ask: - How can I call OnLogin() inside Start()? - I have an image named profilep2. I want the image that I will download from entity files to be synchronized to profilep2, how and where can I do this in the code file

unity3dentitiesphotondata
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image
Seth Du answered

According to your code, when LoadAllFiles() is called, the entity ID and type you have referred is from the previous API callback result. Because PlayFab API calls in Unity SDK are asynchronous, would you please output both variables to ensure the value has been set properly? I suggest moving Line 77 to 75 in the callback result of GetEntityToken API call.

4 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

omerdruu avatar image omerdruu commented ·

Thank you, i think i managed to download the file, i can see "file uploading" notification in unity console thanks to line 85. But has the file been downloaded or is it still being downloaded? I do not know. I want to sync this downloaded image to the image named "profilep2". How will I do this? Also, I do this only when users create or join a room, so that users in the room can see their profile picture. So only each user stores 1 photo and downloads their own photo when they enter the room, for other users to see. Also, the last question I want to ask: Every time the user joins the room, he will interact with the entity files to see both his own photo and the photo of others, and traffic fees will increase in this direction, right? Is there an option for me to minimize this?

0 Likes 0 ·
Seth Du avatar image Seth Du ♦ omerdruu commented ·

GetFiles API call will return URI that can be used via HTTP GET, you can refer to Unity official documentation --UnityWebRequest.downloadProgress to check the progress when using UnityWebRequest.Get.

0 Likes 0 ·
omerdruu avatar image omerdruu Seth Du ♦ commented ·

I'm really struggling with this, sorry to tire you out. I added something inside the GetActualFile():

 UnityWebRequest www = UnityWebRequestTexture.GetTexture(fileData.DownloadUrl);
        yield return www.SendWebRequest();     
        if (www.isError)
        {
            Debug.Log(www.error);
        }   
 
        Texture2D tempPic = new Texture2D(profilep2.mainTexture.width, profilep2.mainTexture.height);
       tempPic = DownloadHandlerTexture.GetContent(www);
    // tempPic = ((DownloadHandlerTexture)www.downloadHandler).texture;
       profilep2.sprite = Sprite.Create(tempPic, new Rect(0, 0, profilep2.mainTexture.width, profilep2.mainTexture.height), new Vector2());

I don't get any error but after download i see an image with red question mark. I guess I can't download the file properly or the file is corrupt?

When I print the "fileData.DownloadUrl" and manually search for this url in google, I am able to download the image

Also, the image I uploaded appears to be 2bytes. Could there be any abnormality?

0 Likes 0 ·
Seth Du avatar image Seth Du ♦ omerdruu commented ·

>>Is there an option for me to minimize this?

Broadcasting is necessary. When a player connects to the server, they need to upload required information and receive all the information cached on the server.

0 Likes 0 ·
omerdruu avatar image
omerdruu answered

https://docs.microsoft.com/en-us/gaming/playfab/features/data/entities/quickstart

I followed this document and it's the same in my code file as in the document. I show the places that are different from each other:

To upload the user's profile picture :

    private void ChooseImage(int maksimumBuyukluk)
    {
        NativeGallery.Permission izin = NativeGallery.GetImageFromGallery((konum) =>
        {
            Debug.Log("Seçilen resmin konumu: " + konum);
            if (konum != null)
            {
                // Seçilen resmi bir Texture2D'ye çevir
                Texture2D texture = NativeGallery.LoadImageAtPath(konum, maksimumBuyukluk);
                System.IO.File.Copy(konum, Application.persistentDataPath + "/SavedImage.png", true);


                if (texture == null)
                {


                    Debug.Log(konum + " konumundaki resimden bir texture oluşturulamadı.");
                    return;
                }


                profilep.sprite = Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), new Vector2(0.5f, 0.5f), 100.0f);
            }
        }, "Bir resim seçin", "image/png");


        Debug.Log("İzin durumu: " + izin);


    }
   
 void OnInitFileUpload(PlayFab.DataModels.InitiateFileUploadsResponse response)
    {




        var payload = File.ReadAllBytes(Application.persistentDataPath + "/SavedImage.png");
        
        GlobalFileLock += 1; // Start SimplePutCall
        PlayFabHttp.SimplePutCall(response.UploadDetails[0].UploadUrl,
            payload,
            FinalizeUpload,
            error => { Debug.Log(error); }
       
            );
        GlobalFileLock -= 1; // Finish InitiateFileUploads


    }

To download the image I uploaded :

 void Start()
    {
       
        if (PlayFabClientAPI.IsClientLoggedIn() == true)
        {
            PlayFabAuthenticationAPI.GetEntityToken(new GetEntityTokenRequest(),
              (entityResult) =>
            {
            
                 entityId = entityResult.Entity.Id;
                 entityType = entityResult.Entity.Type;
               
                Debug.Log(entityId+entityType);
                LoadAllFiles();
             }, OnPlayFabError);


        }
 
    }
 IEnumerator GetActualFile(PlayFab.DataModels.GetFileMetadata fileData)
    {
    
        GlobalFileLock += 1; // Start Each SimpleGetCall
        PlayFabHttp.SimpleGetCall(fileData.DownloadUrl,
            result => { _entityFileJson[fileData.FileName] = Encoding.UTF8.GetString(result); GlobalFileLock -= 1; }, // Finish Each SimpleGetCall           
            error => { Debug.Log(error); }
        
            
        );
        PlayFabClientAPI.UpdateAvatarUrl(new UpdateAvatarUrlRequest()
        {
            ImageUrl = fileData.DownloadUrl  
            
        },
OnSuccess => { },
OnFailed => { }) ; ;


        Debug.Log(fileData.DownloadUrl);
        Debug.Log(fileData.FileName);
        Debug.Log(fileData.Size);


        UnityWebRequest www = UnityWebRequestTexture.GetTexture(fileData.DownloadUrl);
        yield return www.SendWebRequest();     
        Texture2D myTexture = DownloadHandlerTexture.GetContent(www);
        profilep2.sprite = Sprite.Create(myTexture, new Rect(0f, 0f, myTexture.width,myTexture.height), new Vector2(0.5f, 0.5f), 100.0f); ;


    }


Result : I am able to download the image successfully. However, the players participating in the room see the pictures of other players as their own. If there are 4 players in the room, all 4 have the same image. What should I do ? If what I need to do is related to AvatarUrl can you please tell me where and how to do this? Thank you so much @SethDu

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Seth Du avatar image Seth Du ♦ commented ·

If it is a file that needs a client to upload. The above process steps are required. Basic steps are:

  1. The client uploads a file to the server.
  2. The server will send packets to every connected client.

However, the type of file decides if this broadcast is necessary. If using Avatar URL:

  1. A client connects to the server, while sends identity to the server.
  2. Triggers onConnect delegation, and the server will broadcast the PlayFab ID of new player to other connected players.
  3. other connected players will call GetProfile or GetPlayerProfile on the client.

It is also fine to directly get profile on the server, then broadcast AvatarUrl to other clients. It depends on you.

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.