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);
}
}
}