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
Answer by SethDu · Apr 18 at 06:06 AM
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.
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?
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.
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?
>>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.
Answer by omerdruu · Apr 21 at 12:05 AM
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
If it is a file that needs a client to upload. The above process steps are required. Basic steps are:
However, the type of file decides if this broadcast is necessary. If using Avatar URL:
It is also fine to directly get profile on the server, then broadcast AvatarUrl to other clients. It depends on you.