add ready player me POC
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
using ReadyPlayerMe.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class CameraFollow : MonoBehaviour
|
||||
{
|
||||
private const string TARGET_NOT_SET = "Target not set, disabling component";
|
||||
private readonly string TAG = typeof(CameraFollow).ToString();
|
||||
[SerializeField][Tooltip("The camera that will follow the target")]
|
||||
private Camera playerCamera;
|
||||
[SerializeField][Tooltip("The target Transform (GameObject) to follow")]
|
||||
private Transform target;
|
||||
[SerializeField][Tooltip("Defines the camera distance from the player along Z (forward) axis. Value should be negative to position behind the player")]
|
||||
private float cameraDistance = -2.4f;
|
||||
[SerializeField] private bool followOnStart = true;
|
||||
private bool isFollowing;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
SDKLogger.LogWarning(TAG, TARGET_NOT_SET);
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (followOnStart)
|
||||
{
|
||||
StartFollow();
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (isFollowing)
|
||||
{
|
||||
playerCamera.transform.localPosition = Vector3.forward * cameraDistance;
|
||||
playerCamera.transform.localRotation = Quaternion.Euler(Vector3.zero);
|
||||
transform.position = target.position;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopFollow()
|
||||
{
|
||||
isFollowing = false;
|
||||
}
|
||||
|
||||
public void StartFollow()
|
||||
{
|
||||
isFollowing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe759d8a0e88b174a8b7cd5f3d0da425
|
||||
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/QuickStart/Scripts/CameraFollow.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class CameraOrbit : MonoBehaviour
|
||||
{
|
||||
private const float SMOOTH_TIME = 0.1f;
|
||||
|
||||
[SerializeField][Tooltip("PlayerInput component is required to listen for input")]
|
||||
private PlayerInput playerInput;
|
||||
[SerializeField][Tooltip("Used to set lower limit of camera rotation clamping")]
|
||||
private float minRotationX = -60f;
|
||||
[SerializeField][Tooltip("Used to set upper limit of camera rotation clamping")]
|
||||
private float maxRotationX = 50f;
|
||||
|
||||
[SerializeField][Tooltip("Useful to apply smoothing to mouse input")]
|
||||
private bool smoothDamp = false;
|
||||
|
||||
private Vector3 rotation;
|
||||
private Vector3 currentVelocity;
|
||||
|
||||
private float pitch;
|
||||
private float yaw;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
rotation = transform.transform.eulerAngles;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (playerInput == null) return;
|
||||
yaw += playerInput.MouseAxisX ;
|
||||
pitch -= playerInput.MouseAxisY ;
|
||||
|
||||
if (smoothDamp)
|
||||
{
|
||||
rotation = Vector3.SmoothDamp(rotation, new Vector3(pitch, yaw), ref currentVelocity, SMOOTH_TIME);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
rotation = new Vector3(pitch,yaw, rotation.z);
|
||||
}
|
||||
rotation.x = ClampAngle(rotation.x, minRotationX, maxRotationX);
|
||||
transform.transform.rotation = Quaternion.Euler(rotation);
|
||||
}
|
||||
|
||||
private float ClampAngle(float angle, float min, float max)
|
||||
{
|
||||
if (angle < -360F)
|
||||
{
|
||||
angle += 360F;
|
||||
}
|
||||
if (angle > 360F)
|
||||
{
|
||||
angle -= 360F;
|
||||
}
|
||||
return Mathf.Clamp(angle, min, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 731873f07a43384478f87bb5e9cf0f32
|
||||
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/QuickStart/Scripts/CameraOrbit.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class GroundCheck : MonoBehaviour
|
||||
{
|
||||
[SerializeField] [Tooltip("Useful for rough ground")]
|
||||
private float groundedOffset = -0.22f;
|
||||
[SerializeField] [Tooltip("The radius of the grounded check")]
|
||||
private float groundRadius = 0.28f;
|
||||
[SerializeField] [Tooltip("Defines which layers to check for collisions (Should be different from player layer)")]
|
||||
private LayerMask groundMask;
|
||||
|
||||
public bool IsGrounded()
|
||||
{
|
||||
var position = transform.position;
|
||||
Vector3 spherePosition = new Vector3(position.x, position.y + groundedOffset,
|
||||
position.z);
|
||||
return Physics.CheckSphere(spherePosition, groundRadius, groundMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 053ead010be65cf4bb8cdefa80daee41
|
||||
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/QuickStart/Scripts/GroundCheck.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using ReadyPlayerMe;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class LoadingAnimation : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform[] circles;
|
||||
[SerializeField] private float minScaleFactor = 0.1f;
|
||||
|
||||
private CancellationTokenSource ctx;
|
||||
|
||||
private async void OnEnable()
|
||||
{
|
||||
ctx = new CancellationTokenSource();
|
||||
foreach (var circle in circles)
|
||||
{
|
||||
circle.localScale = Vector3.one * minScaleFactor;
|
||||
}
|
||||
|
||||
while (!ctx.IsCancellationRequested)
|
||||
{
|
||||
foreach (var circle in circles)
|
||||
{
|
||||
await circle.LerpScale(Vector3.one * 1f, 0.1f, ctx.Token);
|
||||
try
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(0.1), ctx.Token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
_ = circle.LerpScale(Vector3.one * minScaleFactor, 0.2f, ctx.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
ctx.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44e924d08fe778a41ba076717a6cce90
|
||||
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/QuickStart/Scripts/LoadingAnimation.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,14 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class LookAtCamera : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private GameObject cam;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
transform.LookAt(cam.transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36816fb9717e8a243bf78d3122ff7aa9
|
||||
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/QuickStart/Scripts/LookAtCamera.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,29 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class MouseCursorLock : MonoBehaviour
|
||||
{
|
||||
[SerializeField] [Tooltip("Defines the Cursor Lock Mode to apply")]
|
||||
private CursorLockMode cursorLockMode;
|
||||
[SerializeField] [Tooltip("If true will hide mouse cursor")]
|
||||
private bool hideCursor = true;
|
||||
[SerializeField] [Tooltip("If true it apply cursor settings on start")]
|
||||
private bool applyOnStart = true;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
if (applyOnStart)
|
||||
{
|
||||
Apply();
|
||||
}
|
||||
}
|
||||
|
||||
public void Apply()
|
||||
{
|
||||
Cursor.visible = hideCursor;
|
||||
Cursor.lockState = cursorLockMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee7a0f2cabd18c64dbdec82b601c0b57
|
||||
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/QuickStart/Scripts/MouseCursorLock.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using ReadyPlayerMe.Core;
|
||||
using ReadyPlayerMe.Core.Analytics;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class PersonalAvatarLoader : MonoBehaviour
|
||||
{
|
||||
[Header("UI")]
|
||||
[SerializeField] private Text openPersonalAvatarPanelButtonText;
|
||||
[SerializeField] private Text linkText;
|
||||
[SerializeField] private InputField avatarUrlField;
|
||||
[SerializeField] private Button openPersonalAvatarPanelButton;
|
||||
[SerializeField] private Button closeButton;
|
||||
[SerializeField] private Button linkButton;
|
||||
[SerializeField] private Button loadAvatarButton;
|
||||
[SerializeField] private GameObject avatarLoading;
|
||||
[SerializeField] private GameObject personalAvatarPanel;
|
||||
|
||||
[Header("Character Managers")]
|
||||
[SerializeField] private ThirdPersonLoader thirdPersonLoader;
|
||||
[SerializeField] private CameraOrbit cameraOrbit;
|
||||
[SerializeField] private ThirdPersonController thirdPersonController;
|
||||
|
||||
private string defaultButtonText;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
AnalyticsRuntimeLogger.EventLogger.LogRunQuickStartScene();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
openPersonalAvatarPanelButton.onClick.AddListener(OnOpenPersonalAvatarPanel);
|
||||
closeButton.onClick.AddListener(OnCloseButton);
|
||||
linkButton.onClick.AddListener(OnLinkButton);
|
||||
loadAvatarButton.onClick.AddListener(OnLoadAvatarButton);
|
||||
avatarUrlField.onValueChanged.AddListener(OnAvatarUrlFieldValueChanged);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
openPersonalAvatarPanelButton.onClick.RemoveListener(OnOpenPersonalAvatarPanel);
|
||||
closeButton.onClick.RemoveListener(OnCloseButton);
|
||||
linkButton.onClick.RemoveListener(OnLinkButton);
|
||||
loadAvatarButton.onClick.RemoveListener(OnLoadAvatarButton);
|
||||
avatarUrlField.onValueChanged.RemoveListener(OnAvatarUrlFieldValueChanged);
|
||||
}
|
||||
|
||||
private void OnOpenPersonalAvatarPanel()
|
||||
{
|
||||
linkText.text = $"https://{CoreSettingsHandler.CoreSettings.Subdomain}.readyplayer.me";
|
||||
personalAvatarPanel.SetActive(true);
|
||||
SetActiveThirdPersonalControls(false);
|
||||
AnalyticsRuntimeLogger.EventLogger.LogLoadPersonalAvatarButton();
|
||||
}
|
||||
|
||||
private void OnCloseButton()
|
||||
{
|
||||
SetActiveThirdPersonalControls(true);
|
||||
personalAvatarPanel.SetActive(false);
|
||||
}
|
||||
|
||||
private void OnLinkButton()
|
||||
{
|
||||
Application.OpenURL(linkText.text);
|
||||
}
|
||||
|
||||
private void OnLoadAvatarButton()
|
||||
{
|
||||
thirdPersonLoader.OnLoadComplete += OnLoadComplete;
|
||||
defaultButtonText = openPersonalAvatarPanelButtonText.text;
|
||||
SetActiveLoading(true, "Loading...");
|
||||
|
||||
thirdPersonLoader.LoadAvatar(avatarUrlField.text);
|
||||
personalAvatarPanel.SetActive(false);
|
||||
SetActiveThirdPersonalControls(true);
|
||||
AnalyticsRuntimeLogger.EventLogger.LogPersonalAvatarLoading(avatarUrlField.text);
|
||||
}
|
||||
|
||||
private void OnAvatarUrlFieldValueChanged(string url)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(url) && Uri.TryCreate(url, UriKind.Absolute, out Uri _))
|
||||
{
|
||||
loadAvatarButton.interactable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
loadAvatarButton.interactable = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoadComplete()
|
||||
{
|
||||
thirdPersonLoader.OnLoadComplete -= OnLoadComplete;
|
||||
SetActiveLoading(false, defaultButtonText);
|
||||
}
|
||||
|
||||
private void SetActiveLoading(bool enable, string text)
|
||||
{
|
||||
openPersonalAvatarPanelButtonText.text = text;
|
||||
openPersonalAvatarPanelButton.interactable = !enable;
|
||||
avatarLoading.SetActive(enable);
|
||||
}
|
||||
|
||||
private void SetActiveThirdPersonalControls(bool enable)
|
||||
{
|
||||
cameraOrbit.enabled = enable;
|
||||
thirdPersonController.enabled = enable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 707b0a470d481d94fbbd7427c5d6a880
|
||||
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/QuickStart/Scripts/PersonalAvatarLoader.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class PlayerInput : MonoBehaviour
|
||||
{
|
||||
private const string HORIZONTAL_AXIS = "Horizontal";
|
||||
private const string VERTICAL_AXIS = "Vertical";
|
||||
private const string MOUSE_AXIS_X = "Mouse X";
|
||||
private const string MOUSE_AXIS_Y = "Mouse Y";
|
||||
private const string JUMP_BUTTON = "Jump";
|
||||
|
||||
public Action OnJumpPress;
|
||||
public float AxisHorizontal { get; private set; }
|
||||
public float AxisVertical { get; private set; }
|
||||
public float MouseAxisX { get; private set; }
|
||||
public float MouseAxisY { get; private set; }
|
||||
|
||||
[SerializeField][Tooltip("Defines the mouse sensitivity on the X axis (left and right)")]
|
||||
private float mouseSensitivityX = 1;
|
||||
[SerializeField][Tooltip("Defines the mouse sensitivity on the Y axis (up and down)")]
|
||||
private float mouseSensitivityY = 2;
|
||||
|
||||
public bool IsHoldingLeftShift => Input.GetKey(KeyCode.LeftShift);
|
||||
|
||||
public void CheckInput()
|
||||
{
|
||||
AxisHorizontal = Input.GetAxis(HORIZONTAL_AXIS);
|
||||
AxisVertical = Input.GetAxis(VERTICAL_AXIS);
|
||||
MouseAxisX = Input.GetAxis(MOUSE_AXIS_X) * mouseSensitivityX;
|
||||
MouseAxisY = Input.GetAxis(MOUSE_AXIS_Y) * mouseSensitivityY;
|
||||
if (Input.GetButtonDown(JUMP_BUTTON))
|
||||
{
|
||||
OnJumpPress?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8104def02e7cf0b4db74e40411a44608
|
||||
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/QuickStart/Scripts/PlayerInput.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,100 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
[RequireComponent(typeof(ThirdPersonMovement),typeof(PlayerInput))]
|
||||
public class ThirdPersonController : MonoBehaviour
|
||||
{
|
||||
private const float FALL_TIMEOUT = 0.15f;
|
||||
|
||||
private static readonly int MoveSpeedHash = Animator.StringToHash("MoveSpeed");
|
||||
private static readonly int JumpHash = Animator.StringToHash("JumpTrigger");
|
||||
private static readonly int FreeFallHash = Animator.StringToHash("FreeFall");
|
||||
private static readonly int IsGroundedHash = Animator.StringToHash("IsGrounded");
|
||||
|
||||
private Transform playerCamera;
|
||||
private Animator animator;
|
||||
private Vector2 inputVector;
|
||||
private Vector3 moveVector;
|
||||
private GameObject avatar;
|
||||
private ThirdPersonMovement thirdPersonMovement;
|
||||
private PlayerInput playerInput;
|
||||
|
||||
private float fallTimeoutDelta;
|
||||
|
||||
[SerializeField][Tooltip("Useful to toggle input detection in editor")]
|
||||
private bool inputEnabled = true;
|
||||
private bool isInitialized;
|
||||
|
||||
private void Init()
|
||||
{
|
||||
thirdPersonMovement = GetComponent<ThirdPersonMovement>();
|
||||
playerInput = GetComponent<PlayerInput>();
|
||||
playerInput.OnJumpPress += OnJump;
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
public void Setup(GameObject target, RuntimeAnimatorController runtimeAnimatorController)
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
avatar = target;
|
||||
thirdPersonMovement.Setup(avatar);
|
||||
animator = avatar.GetComponent<Animator>();
|
||||
animator.runtimeAnimatorController = runtimeAnimatorController;
|
||||
animator.applyRootMotion = false;
|
||||
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (avatar == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (inputEnabled)
|
||||
{
|
||||
playerInput.CheckInput();
|
||||
var xAxisInput = playerInput.AxisHorizontal;
|
||||
var yAxisInput = playerInput.AxisVertical;
|
||||
thirdPersonMovement.Move(xAxisInput, yAxisInput);
|
||||
thirdPersonMovement.SetIsRunning(playerInput.IsHoldingLeftShift);
|
||||
}
|
||||
UpdateAnimator();
|
||||
}
|
||||
|
||||
private void UpdateAnimator()
|
||||
{
|
||||
var isGrounded = thirdPersonMovement.IsGrounded();
|
||||
animator.SetFloat(MoveSpeedHash, thirdPersonMovement.CurrentMoveSpeed);
|
||||
animator.SetBool(IsGroundedHash, isGrounded);
|
||||
if (isGrounded)
|
||||
{
|
||||
fallTimeoutDelta = FALL_TIMEOUT;
|
||||
animator.SetBool(FreeFallHash, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fallTimeoutDelta >= 0.0f)
|
||||
{
|
||||
fallTimeoutDelta -= Time.deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
animator.SetBool(FreeFallHash, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnJump()
|
||||
{
|
||||
if (thirdPersonMovement.TryJump())
|
||||
{
|
||||
animator.SetTrigger(JumpHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb4b6cd8da1d3694f9f27a4db307b536
|
||||
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/QuickStart/Scripts/ThirdPersonController.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using ReadyPlayerMe.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
public class ThirdPersonLoader : MonoBehaviour
|
||||
{
|
||||
private readonly Vector3 avatarPositionOffset = new Vector3(0, -0.08f, 0);
|
||||
|
||||
[SerializeField][Tooltip("RPM avatar URL or shortcode to load")]
|
||||
private string avatarUrl;
|
||||
private GameObject avatar;
|
||||
private AvatarObjectLoader avatarObjectLoader;
|
||||
[SerializeField][Tooltip("Animator to use on loaded avatar")]
|
||||
private RuntimeAnimatorController animatorController;
|
||||
[SerializeField][Tooltip("If true it will try to load avatar from avatarUrl on start")]
|
||||
private bool loadOnStart = true;
|
||||
[SerializeField][Tooltip("Preview avatar to display until avatar loads. Will be destroyed after new avatar is loaded")]
|
||||
private GameObject previewAvatar;
|
||||
|
||||
public event Action OnLoadComplete;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
avatarObjectLoader = new AvatarObjectLoader();
|
||||
avatarObjectLoader.OnCompleted += OnLoadCompleted;
|
||||
avatarObjectLoader.OnFailed += OnLoadFailed;
|
||||
|
||||
if (previewAvatar != null)
|
||||
{
|
||||
SetupAvatar(previewAvatar);
|
||||
}
|
||||
if (loadOnStart)
|
||||
{
|
||||
LoadAvatar(avatarUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoadFailed(object sender, FailureEventArgs args)
|
||||
{
|
||||
OnLoadComplete?.Invoke();
|
||||
}
|
||||
|
||||
private void OnLoadCompleted(object sender, CompletionEventArgs args)
|
||||
{
|
||||
if (previewAvatar != null)
|
||||
{
|
||||
Destroy(previewAvatar);
|
||||
previewAvatar = null;
|
||||
}
|
||||
SetupAvatar(args.Avatar);
|
||||
OnLoadComplete?.Invoke();
|
||||
}
|
||||
|
||||
private void SetupAvatar(GameObject targetAvatar)
|
||||
{
|
||||
if (avatar != null)
|
||||
{
|
||||
Destroy(avatar);
|
||||
}
|
||||
|
||||
avatar = targetAvatar;
|
||||
// Re-parent and reset transforms
|
||||
avatar.transform.parent = transform;
|
||||
avatar.transform.localPosition = avatarPositionOffset;
|
||||
avatar.transform.localRotation = Quaternion.Euler(0, 0, 0);
|
||||
|
||||
var controller = GetComponent<ThirdPersonController>();
|
||||
if (controller != null)
|
||||
{
|
||||
controller.Setup(avatar, animatorController);
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadAvatar(string url)
|
||||
{
|
||||
//remove any leading or trailing spaces
|
||||
avatarUrl = url.Trim(' ');
|
||||
avatarObjectLoader.LoadAvatar(avatarUrl);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dcd3a2a3a4803724185a95fcbb555d55
|
||||
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/QuickStart/Scripts/ThirdPersonLoader.cs
|
||||
uploadId: 704624
|
||||
@@ -0,0 +1,112 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace ReadyPlayerMe.Samples.QuickStart
|
||||
{
|
||||
[RequireComponent(typeof(CharacterController), typeof(GroundCheck))]
|
||||
public class ThirdPersonMovement : MonoBehaviour
|
||||
{
|
||||
private const float TURN_SMOOTH_TIME = 0.05f;
|
||||
|
||||
[SerializeField][Tooltip("Used to determine movement direction based on input and camera forward axis")]
|
||||
private Transform playerCamera;
|
||||
[SerializeField][Tooltip("Move speed of the character in")]
|
||||
private float walkSpeed = 3f;
|
||||
[SerializeField][Tooltip("Run speed of the character")]
|
||||
private float runSpeed = 8f;
|
||||
[SerializeField][Tooltip("The character uses its own gravity value. The engine default is -9.81f")]
|
||||
private float gravity = -18f;
|
||||
[SerializeField][Tooltip("The height the player can jump ")]
|
||||
private float jumpHeight = 3f;
|
||||
|
||||
private CharacterController controller;
|
||||
private GameObject avatar;
|
||||
|
||||
private float verticalVelocity;
|
||||
private float turnSmoothVelocity;
|
||||
|
||||
private bool jumpTrigger;
|
||||
public float CurrentMoveSpeed { get; private set; }
|
||||
private bool isRunning;
|
||||
|
||||
private GroundCheck groundCheck;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
controller = GetComponent<CharacterController>();
|
||||
groundCheck = GetComponent<GroundCheck>();
|
||||
}
|
||||
|
||||
public void Setup(GameObject target)
|
||||
{
|
||||
avatar = target;
|
||||
if (playerCamera == null)
|
||||
{
|
||||
playerCamera = Camera.main.transform;
|
||||
}
|
||||
}
|
||||
|
||||
public void Move(float inputX, float inputY)
|
||||
{
|
||||
var moveDirection = playerCamera.right * inputX + playerCamera.forward * inputY;
|
||||
var moveSpeed = isRunning ? runSpeed: walkSpeed;
|
||||
|
||||
JumpAndGravity();
|
||||
controller.Move(moveDirection.normalized * (moveSpeed * Time.deltaTime) + new Vector3(0.0f, verticalVelocity * Time.deltaTime, 0.0f));
|
||||
|
||||
var moveMagnitude = moveDirection.magnitude;
|
||||
CurrentMoveSpeed = isRunning ? runSpeed * moveMagnitude : walkSpeed * moveMagnitude;
|
||||
|
||||
if (moveMagnitude > 0)
|
||||
{
|
||||
RotateAvatarTowardsMoveDirection(moveDirection);
|
||||
}
|
||||
}
|
||||
|
||||
private void RotateAvatarTowardsMoveDirection(Vector3 moveDirection)
|
||||
{
|
||||
float targetAngle = Mathf.Atan2(moveDirection.x, moveDirection.z) * Mathf.Rad2Deg + transform.rotation.y;
|
||||
float angle = Mathf.SmoothDampAngle(avatar.transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, TURN_SMOOTH_TIME);
|
||||
avatar.transform.rotation = Quaternion.Euler(0, angle, 0);
|
||||
}
|
||||
|
||||
private void JumpAndGravity()
|
||||
{
|
||||
if (controller.isGrounded && verticalVelocity< 0)
|
||||
{
|
||||
verticalVelocity = -2f;
|
||||
}
|
||||
|
||||
if (jumpTrigger && controller.isGrounded)
|
||||
{
|
||||
verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
|
||||
jumpTrigger = false;
|
||||
}
|
||||
|
||||
verticalVelocity += gravity * Time.deltaTime;
|
||||
}
|
||||
|
||||
public void SetIsRunning(bool running)
|
||||
{
|
||||
isRunning = running;
|
||||
}
|
||||
|
||||
public bool TryJump()
|
||||
{
|
||||
jumpTrigger = false;
|
||||
if (controller.isGrounded)
|
||||
{
|
||||
jumpTrigger = true;
|
||||
}
|
||||
return jumpTrigger;
|
||||
}
|
||||
|
||||
public bool IsGrounded()
|
||||
{
|
||||
if (verticalVelocity > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return groundCheck.IsGrounded();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd198b5daef562e4d9e07e8e7632cadf
|
||||
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/QuickStart/Scripts/ThirdPersonMovement.cs
|
||||
uploadId: 704624
|
||||
Reference in New Issue
Block a user