using System.Collections; using System.Collections.Generic; using System; using UnityEditorInternal; using UnityEngine; public class Player : MonoBehaviour, IKitchenObjectParent { public static Player Instance { get; private set; } public event EventHandler OnSelectedcounterChanged; public class OnSelectedCounterChangedEventArgs : EventArgs { public ClearCounter selectedCounter; } [SerializeField] private float moveSpeed = 7f; [SerializeField] private GameInput gameInput; [SerializeField] private LayerMask countersLayerMask; [SerializeField] private Transform kitchenObjectHoldPoint; private bool isWalking; private Vector3 lastInteractDir; private ClearCounter selectedCounter; private KitchenObject kitchenObject; private void Start() { gameInput.OnInteractAction += GameInput_OnInteractAction; } private void GameInput_OnInteractAction(object sender, System.EventArgs e) { if (selectedCounter != null) { selectedCounter.Interact(this); } } private void Awake() { if (Instance != null) { Debug.LogError("There is more than one player instance!"); } Instance = this; } private void Update() { HandleMovement(); HandleInteractions(); } public bool IsWalking() { return isWalking; } /// /// Handle object interactions. /// private void HandleInteractions() { Vector2 inputVector = gameInput.GetMovementVectorNormalized(); Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y); // Kepp a constantly updating record of the last move direction. // This means you can interact without holding down a direction. if (moveDir != Vector3.zero) { lastInteractDir = moveDir; } float interactDistance = 2f; if (Physics.Raycast(transform.position, lastInteractDir, out RaycastHit raycastHit, interactDistance, countersLayerMask)) { if (raycastHit.transform.TryGetComponent(out ClearCounter clearCounter)) { // Has Clear Counter if (clearCounter != selectedCounter) { SetSelectedCounter(clearCounter); } } else if (selectedCounter != null) { SetSelectedCounter(null); } } else if (selectedCounter != null) { SetSelectedCounter(null); } } /// /// Handle the player movement and collision. /// private void HandleMovement() { Vector2 inputVector = gameInput.GetMovementVectorNormalized(); Vector3 moveDir = new Vector3(inputVector.x, 0f, inputVector.y); float moveDistance = moveSpeed * Time.deltaTime; float playerRadius = .7f; float playerHeight = 2f; bool canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDir, moveDistance); if (!canMove) { // Cannot move towards moveDir // Attempt only X move Vector3 moveDirX = new Vector3(moveDir.x, 0, 0).normalized; canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDirX, moveDistance); if (canMove) { moveDir = moveDirX; } else { // Cannot move on X so attempt to move on Z Vector3 moveDirZ = new Vector3(0, 0, moveDir.z).normalized; canMove = !Physics.CapsuleCast(transform.position, transform.position + Vector3.up * playerHeight, playerRadius, moveDirZ, moveDistance); if (canMove) { moveDir = moveDirZ; } else { // Cannot move at all } } } if (canMove) { transform.position += moveDir * moveDistance; } isWalking = moveDir != Vector3.zero; float rotateSpeed = 10f; transform.forward = Vector3.Slerp(transform.forward, moveDir, Time.deltaTime * rotateSpeed); } private void SetSelectedCounter(ClearCounter selectedCounter) { this.selectedCounter = selectedCounter; OnSelectedcounterChanged?.Invoke(this, new OnSelectedCounterChangedEventArgs { selectedCounter = selectedCounter, }); } public Transform GetKitchenObjectFollowTransform() { return kitchenObjectHoldPoint; } public void SetKitchenObject(KitchenObject kitchenObject) { this.kitchenObject = kitchenObject; } public KitchenObject GetKitchenObject() { return kitchenObject; } public void ClearKitchenObject() { kitchenObject = null; } public bool HasKitchenObject() { return kitchenObject != null; } }