using UnityEngine; namespace TriLibCore.Samples { /// Represents a class used to control an avatar on TriLib samples. public class AvatarController : AbstractInputSystem { /// The Avatar Controller Singleton instance. public static AvatarController Instance { get; private set; } /// /// Maximum avatar speed in units/second. /// private const float MaxSpeed = 2f; /// /// Avatar acceleration in units/second. /// private const float Acceleration = 5f; /// /// Avatar Friction in units/second. /// private const float Friction = 2f; /// /// Avatar smooth rotation factor. /// private const float RotationSpeed = 60f; /// /// Avatar character controller. /// public CharacterController CharacterController; /// /// Avatar animator. /// public Animator Animator; /// /// Game object that wraps the actual avatar. /// public GameObject InnerAvatar; /// /// Camera offset relative to the avatar. /// private Vector3 _cameraOffset; /// /// Current avatar speed. /// private float _speed; /// /// Camera height offset relative to the avatar. /// private Vector3 _cameraHeightOffset; /// /// Current smooth rotation velocity. /// private float _currentVelocity; /// Configures this instance and calculates the Camera offsets. private void Awake() { Instance = this; _cameraHeightOffset = new Vector3(0f, CharacterController.height * 0.8f, 0f); _cameraOffset = Camera.main.transform.position - transform.position; } /// Handles input (controls the Camera and moves the Avatar character). private void Update() { var input = new Vector3(GetAxis("Horizontal"), 0f, GetAxis("Vertical")); var direction = Camera.main.transform.TransformDirection(input); direction.y = 0f; direction.Normalize(); var targetEulerAngles = direction.magnitude > 0 ? Quaternion.LookRotation(direction).eulerAngles : transform.rotation.eulerAngles; var eulerAngles = transform.rotation.eulerAngles; eulerAngles.y = Mathf.SmoothDampAngle(eulerAngles.y, targetEulerAngles.y, ref _currentVelocity, Time.deltaTime * RotationSpeed * input.magnitude); transform.rotation = Quaternion.Euler(eulerAngles); _speed += input.magnitude * (Acceleration * MaxSpeed) * Time.deltaTime; _speed -= Friction * MaxSpeed * Time.deltaTime; _speed = Mathf.Clamp(_speed, 0f, MaxSpeed); CharacterController.SimpleMove(transform.forward * _speed); Animator.SetFloat("SpeedFactor", _speed / MaxSpeed); var pivotedPosition = Quaternion.AngleAxis(AssetViewerBase.Instance.CameraAngle.x, Vector3.up) * Quaternion.AngleAxis(-AssetViewerBase.Instance.CameraAngle.y, Vector3.right) * _cameraOffset; Camera.main.transform.position = transform.position + _cameraHeightOffset + pivotedPosition; Camera.main.transform.LookAt(transform.position + _cameraHeightOffset); } } }