VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.movement/Shared/Scripts/UI/MovementCharacterSpawnMenu.cs
IonutMocanu 48cccc22ad Main2
2025-09-08 11:13:29 +03:00

162 lines
5.6 KiB
C#

// Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
namespace Meta.XR.Movement.Samples
{
/// <summary>
/// Menu that allows spawning characters.
/// </summary>
public class MovementCharacterSpawnMenu : MonoBehaviour
{
/// <summary>
/// The reference OVRBody to get the joint set from.
/// </summary>
[SerializeField]
protected OVRBody _ovrBody;
/// <summary>
/// Stylized character prefab to spawn.
/// </summary>
[SerializeField]
protected GameObject _stylizedCharacterToSpawn;
/// <summary>
/// High fidelity character prefab to spawn.
/// </summary>
[SerializeField]
protected GameObject _highFidelityCharacterToSpawn;
/// <summary>
/// Parent to spawn under.
/// </summary>
[SerializeField]
protected Transform _spawnParent;
/// <summary>
/// Offset per spawn.
/// </summary>
[SerializeField]
protected Vector3 _spawnOffset = new Vector3(-1.0f, 0.0f, 0.0f);
[SerializeField, InspectorButton("AddStylizedCharacter")]
private bool _spawnStylizedButton;
[SerializeField, InspectorButton("AddHighFidelityCharacter")]
private bool _spawnHighFidelityButton;
private class SpawnMetadata
{
/// <summary>
/// Constructor for spawned character.
/// </summary>
/// <param name="isParentedCharacter">Is parented character.</param>
/// <param name="spawnedObject">Spawned GameObject.</param>
public SpawnMetadata(bool isParentedCharacter,
GameObject spawnedObject)
{
IsParentedCharacter = isParentedCharacter;
SpawnedObject = spawnedObject;
}
/// <summary>
/// Is parented to a transform or not.
/// </summary>
public readonly bool IsParentedCharacter;
/// <summary>
/// Actual spawned character.
/// </summary>
public readonly GameObject SpawnedObject;
}
private const int _characterSpawnLimit = 20;
private Vector3 _currentSpawnOffset, _currentSpawnOffsetNotParented;
private readonly List<SpawnMetadata> _charactersSpawned = new();
/// <summary>
/// Move the non-mirrored characters out further so that they don't intersect any menus to the
/// right of the user.
/// </summary>
private const float _nonMirroredOffsetMultiplier = 1.5f;
private void Awake()
{
Assert.IsNotNull(_stylizedCharacterToSpawn);
_currentSpawnOffset = _spawnOffset;
_currentSpawnOffsetNotParented = -_spawnOffset * _nonMirroredOffsetMultiplier;
}
/// <summary>
/// Add a stylized character to the scene.
/// </summary>
public void AddStylizedCharacter()
{
if (_charactersSpawned.Count >= _characterSpawnLimit)
{
Debug.LogWarning("Reached the limit of characters to spawn.");
return;
}
var newCharacter = Instantiate(_stylizedCharacterToSpawn);
newCharacter.SetActive(true);
newCharacter.GetComponent<OVRBody>().ProvidedSkeletonType = _ovrBody.ProvidedSkeletonType;
AdjustSpawnedCharacterTransform(newCharacter, true, _currentSpawnOffset);
_currentSpawnOffset += _spawnOffset;
_charactersSpawned.Add(new SpawnMetadata(true, newCharacter));
}
/// <summary>
/// Add a high fidelity character to the scene.
/// </summary>
public void AddHighFidelityCharacter()
{
if (_charactersSpawned.Count >= _characterSpawnLimit)
{
Debug.LogWarning("Reached the limit of characters to spawn.");
return;
}
var newCharacter = Instantiate(_highFidelityCharacterToSpawn);
newCharacter.SetActive(true);
newCharacter.GetComponent<OVRBody>().ProvidedSkeletonType = _ovrBody.ProvidedSkeletonType;
AdjustSpawnedCharacterTransform(newCharacter, true, _currentSpawnOffset);
_currentSpawnOffset += _spawnOffset;
_charactersSpawned.Add(new SpawnMetadata(true, newCharacter));
}
/// <summary>
/// Removes last character spawned.
/// </summary>
public void RemoveLastCharacter()
{
if (_charactersSpawned.Count == 0)
{
return;
}
var lastCharacterIndex = _charactersSpawned.Count - 1;
var isLastCharacterParented = _charactersSpawned[lastCharacterIndex].IsParentedCharacter;
Destroy(_charactersSpawned[lastCharacterIndex].SpawnedObject);
_charactersSpawned.RemoveAt(lastCharacterIndex);
if (isLastCharacterParented)
{
_currentSpawnOffset -= _spawnOffset;
}
else
{
_currentSpawnOffsetNotParented += _spawnOffset * _nonMirroredOffsetMultiplier;
}
}
private void AdjustSpawnedCharacterTransform(GameObject newCharacter, bool reparent, Vector3 offsetToUse)
{
var characterTransform = newCharacter.transform;
if (_spawnParent != null && reparent)
{
characterTransform.SetParent(_spawnParent, false);
}
characterTransform.localPosition = offsetToUse;
}
}
}