add ready player me POC
This commit is contained in:
+20
@@ -0,0 +1,20 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3663d6a9358ae4149aad3496e56d4601, type: 3}
|
||||
m_Name: Avatar Configuration LOD0
|
||||
m_EditorClassIdentifier:
|
||||
MeshLod: 0
|
||||
Pose: 0
|
||||
TextureAtlas: 1
|
||||
TextureSizeLimit: 1024
|
||||
UseHands: 0
|
||||
MorphTargets: []
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99552ccf737554f2fab58e864f9416e4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/Avatar
|
||||
Configuration LOD0.asset
|
||||
uploadId: 704624
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3663d6a9358ae4149aad3496e56d4601, type: 3}
|
||||
m_Name: Avatar Configuration LOD1
|
||||
m_EditorClassIdentifier:
|
||||
MeshLod: 1
|
||||
Pose: 0
|
||||
TextureAtlas: 2
|
||||
TextureSizeLimit: 512
|
||||
UseHands: 0
|
||||
MorphTargets: []
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d2a8b01037e24f54b99b6aa9a51f0db
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/Avatar
|
||||
Configuration LOD1.asset
|
||||
uploadId: 704624
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 3663d6a9358ae4149aad3496e56d4601, type: 3}
|
||||
m_Name: Avatar Configuration LOD2
|
||||
m_EditorClassIdentifier:
|
||||
MeshLod: 2
|
||||
Pose: 0
|
||||
TextureAtlas: 3
|
||||
TextureSizeLimit: 256
|
||||
UseHands: 0
|
||||
MorphTargets:
|
||||
- none
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5fba8af1affda4895895126e539c6165
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/Avatar
|
||||
Configuration LOD2.asset
|
||||
uploadId: 704624
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ReadyPlayerMe.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.AvatarLoading
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is a simple <see cref="Monobehaviour"/> to serve as an example on how to load a Ready Player Me avatar with multiple LOD's (level of detail) and spawn as a <see cref="GameObject"/> into the scene at runtime.
|
||||
/// </summary>
|
||||
public class AvatarLodExample : MonoBehaviour
|
||||
{
|
||||
private const string LOD_MESH_SUFFIX = "_LOD";
|
||||
private const float CULL_TRANSITION = 0.05f;
|
||||
|
||||
[SerializeField]
|
||||
private AvatarLodExampleUI lodExampleUI;
|
||||
[SerializeField] [Tooltip("Set this to the URL or shortcode of the Ready Player Me Avatar you want to load.")]
|
||||
private string avatarUrl;
|
||||
[SerializeField]
|
||||
private AvatarConfig[] lodConfigs;
|
||||
|
||||
private LODGroup lodGroup;
|
||||
private bool loading;
|
||||
private GameObject mainAvatar;
|
||||
private SkinnedMeshRenderer mainMeshRenderer;
|
||||
private readonly List<SkinnedMeshRenderer> meshRenderersList = new List<SkinnedMeshRenderer>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
ApplicationData.Log();
|
||||
if (lodExampleUI) lodExampleUI.Init();
|
||||
LoadLodAvatar();
|
||||
}
|
||||
|
||||
/// Loads all the avatar LOD's as per the lodConfigs length and configuration
|
||||
private async void LoadLodAvatar()
|
||||
{
|
||||
var avatarMetadata = new AvatarMetadata();
|
||||
|
||||
foreach (var config in lodConfigs)
|
||||
{
|
||||
var lodLevel = (int) config.Lod;
|
||||
|
||||
var loader = new AvatarObjectLoader();
|
||||
loader.AvatarConfig = config;
|
||||
loader.LoadAvatar(avatarUrl);
|
||||
// use the OnCompleted event to setup the mesh renderers
|
||||
loader.OnCompleted += (sender, args) =>
|
||||
{
|
||||
if (mainAvatar == null)
|
||||
{
|
||||
avatarMetadata = args.Metadata;
|
||||
mainAvatar = Instantiate(args.Avatar);
|
||||
mainAvatar.name = args.Avatar.name + LOD_MESH_SUFFIX;
|
||||
|
||||
mainMeshRenderer = mainAvatar.GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
var meshTransform = mainMeshRenderer.transform;
|
||||
meshTransform.name = meshTransform.name += $"{LOD_MESH_SUFFIX}{lodLevel}";
|
||||
mainMeshRenderer.enabled = false;
|
||||
meshRenderersList.Add(mainMeshRenderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var lodSkinnedMeshRenderer = args.Avatar.GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
lodSkinnedMeshRenderer.rootBone = mainMeshRenderer.rootBone;
|
||||
lodSkinnedMeshRenderer.bones = mainMeshRenderer.bones;
|
||||
lodSkinnedMeshRenderer.transform.name += $"{LOD_MESH_SUFFIX}{lodLevel}";
|
||||
lodSkinnedMeshRenderer.transform.SetParent(mainAvatar.transform);
|
||||
lodSkinnedMeshRenderer.transform.SetSiblingIndex(lodLevel);
|
||||
lodSkinnedMeshRenderer.enabled = false;
|
||||
meshRenderersList.Add(lodSkinnedMeshRenderer);
|
||||
}
|
||||
|
||||
Destroy(args.Avatar);
|
||||
|
||||
loading = false;
|
||||
};
|
||||
loading = true;
|
||||
|
||||
while (loading)
|
||||
{
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
AddLodGroup();
|
||||
AvatarAnimationHelper.SetupAnimator(avatarMetadata, mainAvatar);
|
||||
if (lodExampleUI) lodExampleUI.Show();
|
||||
}
|
||||
|
||||
/// Adds and configures the LODGroup component
|
||||
private void AddLodGroup()
|
||||
{
|
||||
lodGroup = mainAvatar.AddComponent<LODGroup>();
|
||||
var lods = new LOD[lodConfigs.Length];
|
||||
for (var i = 0; i < lodConfigs.Length; i++)
|
||||
{
|
||||
meshRenderersList[i].enabled = true;
|
||||
lods[i] = new LOD(CalculateTransitionHeight(i), new Renderer[] { meshRenderersList[i] });
|
||||
}
|
||||
lodGroup.SetLODs(lods);
|
||||
lodGroup.RecalculateBounds();
|
||||
|
||||
lodExampleUI.LodGroup = lodGroup;
|
||||
}
|
||||
|
||||
private float CalculateTransitionHeight(int lodConfig)
|
||||
{
|
||||
var lodTransition = (lodConfig + 1f) / lodConfigs.Length;
|
||||
return (1 - lodTransition + CULL_TRANSITION);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (mainAvatar != null)
|
||||
{
|
||||
Destroy(mainAvatar);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 707cd498ac29848c587fbf68dc32aa85
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/AvatarLodExample.cs
|
||||
uploadId: 704624
|
||||
+2751
File diff suppressed because it is too large
Load Diff
+14
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70100edf1a7db4b519c15b52da0e13f2
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/AvatarLodExample.unity
|
||||
uploadId: 704624
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.AvatarLoading
|
||||
{
|
||||
public class AvatarLodExampleUI : MonoBehaviour
|
||||
{
|
||||
private Slider uiSlider;
|
||||
private Vector3 cameraStartPos;
|
||||
private Text lodInfoText;
|
||||
|
||||
[SerializeField] private Camera mainCamera;
|
||||
|
||||
public LODGroup LodGroup { set; get; }
|
||||
|
||||
public void Init()
|
||||
{
|
||||
QualitySettings.lodBias = 1f;
|
||||
lodInfoText = GetComponentInChildren<Text>();
|
||||
uiSlider = GetComponentInChildren<Slider>();
|
||||
cameraStartPos = mainCamera ? mainCamera.transform.position : Vector3.zero;
|
||||
uiSlider.onValueChanged.AddListener(UpdatePosition);
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
GetComponent<Canvas>().enabled = true;
|
||||
}
|
||||
|
||||
private void UpdatePosition(float value)
|
||||
{
|
||||
mainCamera.transform.position = new Vector3(cameraStartPos.x, cameraStartPos.y, cameraStartPos.z + value);
|
||||
Invoke(nameof(UpdateCurrentLod), 0.1f);
|
||||
}
|
||||
|
||||
private void UpdateCurrentLod()
|
||||
{
|
||||
if (LodGroup != null)
|
||||
{
|
||||
Transform lodTransform = LodGroup.transform;
|
||||
foreach (Transform child in lodTransform)
|
||||
{
|
||||
var thisRenderer = child.GetComponent<SkinnedMeshRenderer>();
|
||||
if (thisRenderer != null && thisRenderer.isVisible)
|
||||
{
|
||||
var currentLod = child.name.Split('_').Last();
|
||||
var vertexCount = thisRenderer.sharedMesh.vertexCount;
|
||||
var textureSize = thisRenderer.sharedMaterial.mainTexture.height;
|
||||
var morphTargetCount = thisRenderer.sharedMesh.blendShapeCount;
|
||||
UpdateLodInfoPanel(currentLod, vertexCount, textureSize, morphTargetCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLodInfoPanel(string currentLod, int vertexCount, int textureSize, int morphTargetCount)
|
||||
{
|
||||
lodInfoText.text = "Current LOD\n" + currentLod + "\n" +
|
||||
"Vertex Count\n" + vertexCount + "\n" +
|
||||
"Texture Size\n" + textureSize + "\n" +
|
||||
"Blend Shapes\n" + morphTargetCount;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
uiSlider.onValueChanged.RemoveAllListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 260ad8794b02546e5b200807e952ba36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 259814
|
||||
packageName: Ready Player Me Avatar and Character Creator
|
||||
packageVersion: 7.3.1
|
||||
assetPath: Assets/Ready Player Me/Core/Samples/AvatarLoadingSamples/AvatarLod/AvatarLodExampleUI.cs
|
||||
uploadId: 704624
|
||||
Reference in New Issue
Block a user