KitchenChaos/Assets/Scripts/Player.cs

161 lines
5.4 KiB
C#

using System;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
public class Player : NetworkBehaviour, IKitchenObjectParent {
private const float playerRadius = .7f;
// private const float playerHeight = 2f;
[SerializeField] private float MoveSpeed = 7f;
[SerializeField] private float RotateSpeed = 10f;
[SerializeField] private float InteractDistance = 2f;
[SerializeField] private LayerMask CountersLayerMask;
[SerializeField] private LayerMask CollisionsLayerMask;
[SerializeField] private List<Vector3> SpawnPositionList;
[SerializeField] private Transform KitchenObjectHoldPoint;
[SerializeField] private PlayerColor PlayerColor;
private Vector2 inputVector;
private bool isWalking;
private KitchenObject kitchenObject;
private Vector3 lastInteractDir;
private Vector3 moveDir;
private BaseCounter selectedCounter;
public static Player LocalInstance { get; private set; }
private void Start() {
GameInput.Instance.OnInteractAction += GameInput_OnInteractAction;
GameInput.Instance.OnInteractAlternateAction += GameInput_OnInteractAlternateAction;
PlayerData playerData = KitchenGameMultiplayer.Instance.GetPlayerDataFromClientId(OwnerClientId);
PlayerColor.SetPlayerColor(KitchenGameMultiplayer.Instance.GetPlayerColor(playerData.ColorId));
}
private void Update() {
if (!IsOwner) return;
HandleMovement();
HandleInteractions();
}
public KitchenObject KitchenObject {
get => kitchenObject;
set {
kitchenObject = value;
if (value is null) return;
OnPickedSomething?.Invoke(this, EventArgs.Empty);
OnAnyPickedSomething?.Invoke(this, EventArgs.Empty);
}
}
public Transform GetKitchenObjectFollowTransform() => KitchenObjectHoldPoint;
public NetworkObject GetNetworkObject() => NetworkObject;
public static event EventHandler OnAnyPlayerSpawned;
public static event EventHandler OnAnyPickedSomething;
public static void ResetStaticData() {
OnAnyPlayerSpawned = null;
OnAnyPickedSomething = null;
}
public event EventHandler OnPickedSomething;
public override void OnNetworkSpawn() {
if (IsOwner) {
LocalInstance = this;
KitchenObjectHoldPoint = transform.Find("KitchenObjectHoldPoint");
}
transform.position = SpawnPositionList[KitchenGameMultiplayer.Instance.GetPlayerDataIndexFromClientId(OwnerClientId)];
OnAnyPlayerSpawned?.Invoke(this, EventArgs.Empty);
if (IsServer) NetworkManager.Singleton.OnClientDisconnectCallback += NetworkManager_OnClientDisconnectCallback;
}
private void NetworkManager_OnClientDisconnectCallback(ulong clientId) {
if (clientId == OwnerClientId && KitchenObject is not null) KitchenObject.DestroyKitchenObject(KitchenObject);
}
public event EventHandler<SelectedCounterChangedEventArgs> OnSelectedCounterChanged;
private void GameInput_OnInteractAlternateAction(object sender, EventArgs e) {
if (!KitchenGameManager.Instance.IsGamePlaying()) return;
if (selectedCounter != null) selectedCounter.InteractAlternate(this);
}
private void GameInput_OnInteractAction(object sender, EventArgs e) {
if (!KitchenGameManager.Instance.IsGamePlaying()) return;
if (selectedCounter != null) selectedCounter.Interact(this);
}
private void HandleInteractions() {
inputVector = GameInput.GetMovementVectorNormalized();
if (moveDir != Vector3.zero) lastInteractDir = moveDir;
if (Physics.Raycast(transform.position, lastInteractDir, out RaycastHit raycastHit, InteractDistance, CountersLayerMask)) {
if (raycastHit.transform.TryGetComponent(out BaseCounter baseCounter)) {
if (baseCounter != selectedCounter) SetSelectedCounter(baseCounter);
}
else {
SetSelectedCounter(null);
}
}
else {
SetSelectedCounter(null);
}
}
private void SetSelectedCounter(BaseCounter value) {
selectedCounter = value;
OnSelectedCounterChanged?.Invoke(this, new() { SelectedCounter = value });
}
public bool IsWalking() => isWalking;
private void HandleMovement() {
inputVector = GameInput.GetMovementVectorNormalized();
moveDir = new(inputVector.x, 0, inputVector.y);
if (moveDir == Vector3.zero) return;
float moveDistance = MoveSpeed * Time.deltaTime;
Vector3 position = transform.position;
bool canMove = !Physics.BoxCast(position, Vector3.one * playerRadius, moveDir, Quaternion.identity, moveDistance, CollisionsLayerMask);
if (!canMove) {
// Cannot move towars moveDir
//Attempt only x movement
Vector3 moveDirX = new Vector3(moveDir.x, 0, 0).normalized;
canMove = moveDir.x is < -.5f or > +.5f && !Physics.BoxCast(position, Vector3.one * playerRadius, moveDirX, Quaternion.identity, moveDistance, CollisionsLayerMask);
if (canMove) {
//Can move only on the X
MovePlayer(moveDirX, moveDistance);
}
else {
//Cannot move only on the X
//Attempt only Z movement
Vector3 moveDirZ = new Vector3(0, 0, moveDir.z).normalized;
canMove = moveDir.z is < -.5f or > +.5f && !Physics.BoxCast(position, Vector3.one * playerRadius, moveDirZ, Quaternion.identity, moveDistance, CollisionsLayerMask);
if (canMove)
//Can move only on the Z
MovePlayer(moveDirZ, moveDistance);
//Cannot move in any direction
}
}
else {
MovePlayer(moveDir, moveDistance);
}
isWalking = moveDir != Vector3.zero;
transform.forward = Vector3.Slerp(transform.forward, moveDir, Time.deltaTime * RotateSpeed);
}
private void MovePlayer(Vector3 moveDirection, float moveDistance) => transform.position += moveDirection * moveDistance;
}