You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
4.5 KiB
C#

using Fusion;
using UnityEngine;
using Fusion.Addons.SimpleKCC;
namespace Projectiles
{
/// <summary>
/// Main script handling player agent. It provides access to common components and handles movement input processing and camera.
/// </summary>
[DefaultExecutionOrder(-5)]
[RequireComponent(typeof(Weapons), typeof(Health), typeof(SimpleKCC))]
public class PlayerAgent : ContextBehaviour
{
// PUBLIC MEMBERS
[Networked]
public Player Owner { get; set; }
public Weapons Weapons { get; private set; }
public Health Health { get; private set; }
public SimpleKCC KCC { get; private set; }
public PlayerInput Input { get; private set; }
public bool InputBlocked => Health.IsAlive == false;
// PRIVATE MEMBERS
[SerializeField]
private Transform _cameraPivot;
[SerializeField]
private Transform _cameraHandle;
[Header("Movement")]
[SerializeField]
private float _moveSpeed = 6f;
[SerializeField]
public float _upGravity = 15f;
[SerializeField]
public float _downGravity = 25f;
[SerializeField]
private float _maxCameraAngle = 75f;
[SerializeField]
private float _jumpImpulse = 6f;
[SerializeField]
public float _groundAcceleration = 55f;
[SerializeField]
public float _groundDeceleration = 25f;
[SerializeField]
public float _airAcceleration = 25f;
[SerializeField]
public float _airDeceleration = 1.3f;
[Networked]
private Vector3 _moveVelocity { get; set; }
private Vector2 _lastFUNLookRotation;
// NetworkBehaviour INTERFACE
public override void Spawned()
{
name = Object.InputAuthority.ToString();
// Only local player needs networked properties (move velocity).
// This saves network traffic by not synchronizing networked properties to other clients except local player.
ReplicateToAll(false);
ReplicateTo(Object.InputAuthority, true);
}
public override void Despawned(NetworkRunner runner, bool hasState)
{
Owner = null;
}
public override void FixedUpdateNetwork()
{
if (Owner != null && Health.IsAlive == true)
{
ProcessMovementInput();
}
// Setting camera pivot rotation
var pitchRotation = KCC.GetLookRotation(true, false);
_cameraPivot.localRotation = Quaternion.Euler(pitchRotation);
_lastFUNLookRotation = KCC.GetLookRotation();
}
// MONOBEHAVIOUR
protected void Awake()
{
KCC = GetComponent<SimpleKCC>();
Weapons = GetComponent<Weapons>();
Health = GetComponent<Health>();
Input = GetComponent<PlayerInput>();
}
protected void LateUpdate()
{
if (HasInputAuthority == true && Owner != null && Health.IsAlive == true)
{
// For responsive look experience we use last FUN look + accumulated look rotation delta
KCC.SetLookRotation(_lastFUNLookRotation + Input.AccumulatedLook, -_maxCameraAngle, _maxCameraAngle);
}
// Update camera pitch
// Camera pivot influences also weapon rotation so it needs to be set on proxies as well
var pitchRotation = KCC.GetLookRotation(true, false);
_cameraPivot.localRotation = Quaternion.Euler(pitchRotation);
if (HasInputAuthority == true)
{
var cameraTransform = Context.Camera.transform;
// Setting base camera transform based on handle
cameraTransform.position = _cameraHandle.position;
cameraTransform.rotation = _cameraHandle.rotation;
}
}
// PRIVATE METHODS
private void ProcessMovementInput()
{
if (GetInput(out GameplayInput input) == false)
return;
KCC.AddLookRotation(input.LookRotationDelta, -_maxCameraAngle, _maxCameraAngle);
// It feels better when player falls quicker
KCC.SetGravity(KCC.RealVelocity.y >= 0f ? _upGravity : _downGravity);
// Calculate input direction based on recently updated look rotation (the change propagates internally also to KCC.TransformRotation)
var inputDirection = KCC.TransformRotation * new Vector3(input.MoveDirection.x, 0f, input.MoveDirection.y);
var desiredMoveVelocity = inputDirection * _moveSpeed;
float acceleration = 1f;
if (desiredMoveVelocity == Vector3.zero)
{
// No desired move velocity - we are stopping.
acceleration = KCC.IsGrounded == true ? _groundDeceleration : _airDeceleration;
}
else
{
acceleration = KCC.IsGrounded == true ? _groundAcceleration : _airAcceleration;
}
_moveVelocity = Vector3.Lerp(_moveVelocity, desiredMoveVelocity, acceleration * Runner.DeltaTime);
float jumpImpulse = input.Buttons.WasPressed(Input.PreviousButtons, EInputButton.Jump) && KCC.IsGrounded ? _jumpImpulse : 0f;
KCC.Move(_moveVelocity, jumpImpulse);
}
}
}