提问人:Mashimaro7 提问时间:5/24/2023 最后编辑:cocomacMashimaro7 更新时间:5/28/2023 访问量:44
Unity API 返回 Vector3,但值错误
Unity API Returning Vector3s but the Values are Wrong
问:
我正在使用 Replicate API 尝试在 Unity 中获取点云。我终于让 API 返回一个 JSON 文件,我很确定它返回了每个点的位置。然而,当我将其转换为 vector3 时,这些值变得异常,每个数字都类似于 6.852349e-43,甚至一些“NaN”,在 API 上它们似乎都是低于 0 的值。vector3
这是它们在 Replicate 页面上的样子,
"coords": [
[
-0.039118800312280655,
-0.25740715861320496,
0.28050559759140015
],
[
0.13176295161247253,
0.23972494900226593,
-0.06013050675392151
],
然而,当我在 Unity 中将它们转换为 a 时,它们像这样返回,我假设我不应该将它们转换为 ?Replicate 的页面显示“坐标”是 (X,Y,Z) 点坐标的 [N x 3] 数组“,经过广泛的谷歌搜索,我不知道 NX3 是什么意思。我试过 , , 而不是 ,但是唯一一个从 JSON 文件中正确分配的,(使用
vector3
vector3
float[,]
float[,,]
float[][]
vector3
vector3
JsonUtility.FromJson
)
这是我调用 api 的脚本,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using SimpleJSON;
public class Prompt
{
public string prompt;
}
public class PostResponse
{
public string completed_at;
public string created_at;
public string error;
public string id;
public Prompt input;
public string[] logs;
public string metrics;
public Output output;
public string started_at;
public string status;
public string version;
}
public class ReplicateAPI : MonoBehaviour
{
private string API_ENDPOINT = "https://api.replicate.com/v1/predictions";
private string REPLICATE_API_TOKEN = "r8_DhOE6C7LuA7edPvLh7Io0ukwbmXCLEY450vc3";
[SerializeField] PointEResponse response;
public string prompt = "dog";
[SerializeField] Material material;
[SerializeField] MeshFilter meshFilter;
private void Start()
{
StartCoroutine(Predict());
}
IEnumerator Predict()
{
string requestData = $@"{{
""version"": ""1a4da7adf0bc84cd786c1df41c02db3097d899f5c159f5fd5814a11117bdf02b"",
""input"": {{
""prompt"": ""{prompt}"",
""output_format"": ""json_file""
}}
}}";
UnityWebRequest request = UnityWebRequest.Put(API_ENDPOINT, requestData);
request.method = "POST";
request.SetRequestHeader("Authorization", "Token " + REPLICATE_API_TOKEN);
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Error " + request.responseCode + ": " + request.error);
StartCoroutine(Predict());
}
else
{
Debug.Log(request.downloadHandler.text);
PostResponse response = JsonUtility.FromJson<PostResponse>(request.downloadHandler.text);
StartCoroutine(GetResult(response.id));
}
}
IEnumerator GetResult(string id)
{
yield return new WaitForSeconds(5);
UnityWebRequest request = UnityWebRequest.Get(API_ENDPOINT + "/" + id);
request.SetRequestHeader("Authorization", "Token " + REPLICATE_API_TOKEN);
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
{
Debug.LogError("Error " + request.responseCode + ": " + request.error);
yield break;
}
else
{
response = JsonUtility.FromJson<PointEResponse>(request.downloadHandler.text);
Debug.Log(request.downloadHandler.text);
}
if (response.status != "succeeded") StartCoroutine(GetResult(id));
else
{
if (response.output.json_file.colors != null && response.output.json_file.colors.Length > 0)
{
for (int i = 0; i < response.output.json_file.colors.Length; i++)
{
GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
g.transform.localScale = Vector3.one / 100;
g.transform.position = new Vector3(response.output.json_file.coords[i].x, response.output.json_file.coords[i].y, response.output.json_file.coords[i].z);
Material m = new Material(material);
m.color = new Color(response.output.json_file.colors[i].x, response.output.json_file.colors[i].y, response.output.json_file.colors[i].z);
g.GetComponent<MeshRenderer>().material = m;
}
}
else
{
StartCoroutine(GetResult(id));
}
}
}
}
“response”类如下所示,
using System;
using UnityEngine;
[Serializable]
public class PointEResponse
{
public string id;
public string version;
public Urls urls;
public DateTime created_at;
public DateTime started_at;
public DateTime completed_at;
public string source;
public string status;
public Prompt input;
public Output output;
public object error;
public string[] logs;
public Metrics metrics;
}
[Serializable]
public class Output
{
public JsonFile json_file;
}
[Serializable]
public class JsonFile
{
public Vector3[] coords;
public Vector3[] colors;
}
public class Urls
{
public string get;
public string cancel;
}
public class Metrics
{
public float predict_time;
}
其中输出包含每个坐标的坐标和颜色。我假设我不应该将这些转换为 Vector3,但我已经尝试了我所知道的所有其他方法,其中唯一一个甚至返回任何形式的。
如何解决此问题?
答:
您在此处获取的 JSON 不会直接匹配。Vector3
Afaik a 不能直接 JSON(反)序列化。Vector3
"coords": [
[
-0.039118800312280655,
-0.25740715861320496,
0.28050559759140015
],
[
0.13176295161247253,
0.23972494900226593,
-0.06013050675392151
],
意味着你得到的东西看起来很像
[Serializable]
public class JsonFile
{
public float[][] coords;
// assuming same layout for those
public float[][] colors;
}
我猜,如果以及如何在内存中将其布置成结构,那将是黑魔法。Vector3
但是,内置的 /Unity 的序列化程序也不会支持这种类型的复杂集合!JsonUtility
您宁愿需要第三方库,例如 通过包管理器以包的形式提供Newtonsoft Json.NET
相反,你会去例如
using UnityEngine.Scripting;
using Newtonsoft.Json;
...
[Serializable]
public class JsonFile
{
public Vector3[] coords;
public Color[] colors;
// using a JsonConstructor you can directly here ensure your given Json data format is
// translated in usable types and structure
// If this attribute is present Newtonsoft will automatically not directly assign the fields but rather use this constructor
// The [Preserve] is to ensure this constructor is not stripped of while building since nothing else will be ever using it
[Preserve]
[JsonConstructor]
public JsonFile(float[][] coords, float[][] colors)
{
this.coords = new Vector3[coords.GetLength(0)];
for (var i = 0; i < this.coords.Length; i++)
{
this.coords[i] = new Vector3(coords[i][0], coords[i][1], coords[i][2]);
}
this.colors = new Color[colors.GetLength(0)];
for(var i = 0; i < this.colors.Length; i++)
{
this.colors[i] = new Color(colors[i][0], colors[i][1], colors[i][2]);
}
}
}
然后去
var response = JsonConvert.DeserializeObject<PostResponse>(request.downloadHandler.text);
顺便说一句,因为这是一个结构,你只是简单地做Vector3
g.transform.position = response.output.json_file.coords[i];
...
m.color = nresponse.output.json_file.colors[i];
评论
float[]
Vector3
Color
评论
N x 3
float[N * 3]
N = amount of points
float[][]
float[][]