using System.Collections; using System.Collections.Generic; using Mirror; using UnityEngine; using UnityEngine.Audio; public class PlayerController : NetworkBehaviour { public Rigidbody2D rigidbody; public SpriteRenderer sprite; public bool invertSprite; public Animator animator; public LayerMask groundLayerMask; // public float drownedDepth; public bool isGrounded = true; public bool isSwimming = false; public Transform groundChecker; public Vector2 gravity; public float buoyantForce; public float buoyantSpd; public float moveSpeed = 1; public float jumpForce = 10; public float jumpDuration = 0.2f; public AudioClip jumpSFX; float jumpT = 0; public bool listenToInput = true; public bool inDoor = false; public bool insideDoor = false; bool enteringDoor = false; public Vector3 neighboursDetectorSize; void Start() { jumpT = jumpDuration; if (!isServer) { rigidbody.simulated = false; } } [SyncVar] bool _grounded = false; bool jumpReleased = true; [HideInInspector] public bool inWater; [SyncVar] public bool InteractionKeyPressed; [SyncVar] public bool JumpKeyPressed; [SyncVar] public float HorizontalAxis; public float moveInput = 0; [Command] void CmdUpdateInput(float _horizontal, bool jump, bool interact) { HorizontalAxis = _horizontal; JumpKeyPressed = jump; InteractionKeyPressed = interact; } void ListenInput() { HorizontalAxis = 0; if (Input.GetKey(InputManager.data().leftInput)) { HorizontalAxis = -1; } else if (Input.GetKey(InputManager.data().rightInput)) { HorizontalAxis = 1; } JumpKeyPressed = Input.GetKey(InputManager.data().jumpInput); InteractionKeyPressed = Input.GetKey(InputManager.data().interactingKey); } void FixedUpdate() { if (isLocalPlayer) { // <-- First Listen to inputs no matter in server or not, but if the lcoal player ListenInput(); } Movement();//SImulate everywhere if (isServer) { //Simulate physics on server RpcUpdatePosition(transform.position, HorizontalAxis, rigidbody.velocity, NetworkTime.time); } else { if (isLocalPlayer) { //I aint the server, but the local player. I move! CmdUpdateInput(HorizontalAxis, JumpKeyPressed, InteractionKeyPressed); } } } [ClientRpc] void RpcUpdatePosition(Vector3 position, float horizontalAxis, Vector3 velocity, double time) { double latency = NetworkTime.time - time; int framesSkipped = Mathf.FloorToInt((float)(latency * 50)); Debug.Log($"Missed {framesSkipped} frames due to network"); if (Vector3.Distance(transform.position, position) > 0.15f) { transform.position = position; rigidbody.velocity = velocity; } // if(isLocalPlayer){ // //Client prediction // if(Vector3.Distance(transform.position, position) > 0.5f){ // transform.position = position; // rigidbody.velocity= velocity; // } // }else{ // //Just update the position // transform.position = Vector3.Lerp(transform.position, position, 0.1f); // rigidbody.velocity=velocity; // } } void Movement() { isGrounded = getGrounded(); if (_grounded != isGrounded) { if (isGrounded) { OnLand(); } else { OnFly(); } _grounded = isGrounded; } if (isSwimming) { rigidbody.velocity = new Vector2(rigidbody.velocity.x, Mathf.Lerp(rigidbody.velocity.y, buoyantForce, buoyantSpd)); if ((JumpKeyPressed)) { rigidbody.velocity = new Vector2(rigidbody.velocity.x, jumpForce / 12f); } } else { gravity = new Vector2(gravity.x, 0); } //Gravity Application rigidbody.AddForce(gravity); //Update In-Air value on animation animator.SetBool("inAir", !isGrounded); animator.SetBool("isOnWater", inWater); // if (GameManager.isPaused) { HorizontalAxis = 0; } //Move according to input //Exit the door if (enteringDoor && !InteractionKeyPressed) { enteringDoor = false; } if (insideDoor && !enteringDoor && InteractionKeyPressed) { Debug.Log("Exiting door"); transform.position = SceneData.netSceneData.door.transform.position; insideDoor = false; enteringDoor = true; if (GetComponent() != null) { GetComponent().CallChangeInsideDoor(insideDoor); } } if (listenToInput) { if (isGrounded) { moveInput = HorizontalAxis; } else { //Change moveInput while in-air | IF there is an input // if (Input.GetKey(InputManager.data().leftInput) || Input.GetKey(InputManager.data().rightInput)) if (HorizontalAxis != 0) { moveInput = Mathf.Lerp(moveInput, HorizontalAxis, 0.2f); } } //Enter the door if (inDoor && InteractionKeyPressed && !enteringDoor) { if (SceneData.netSceneData.doorExit != null) { Debug.Log("Entering door"); transform.DetachChildren(); transform.position = SceneData.netSceneData.doorExit.position; insideDoor = true; enteringDoor = true; if (GetComponent() != null) { GetComponent().CallChangeInsideDoor(insideDoor); } } } } if (isSwimming || inWater) { moveInput = moveInput / 2f; } //Update moving value on Animation animator.SetBool("moving", (moveInput != 0)); animator.SetBool("isSwimming", isSwimming); //Flip Image to face moving Direction if (moveInput < 0) { sprite.flipX = (invertSprite) ? false : true; } else if (moveInput > 0) { sprite.flipX = (invertSprite) ? true : false; } //Apply moving input to player // if (GetComponent() != null) // { // if (GetComponent().parentFrnd != null) // { // rigidbody.velocity = GetComponent().parentFrnd.GetComponent().velocity; // } // } rigidbody.transform.Translate(new Vector2(moveSpeed * moveInput, 0)); if (moveInput == 0) { rigidbody.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezeRotation; } else { rigidbody.constraints = RigidbodyConstraints2D.FreezeRotation; } bool _canJump = canJump(); if ((JumpKeyPressed) && _canJump) { jumpT = 0; jumpReleased = false; rigidbody.velocity = new Vector2(rigidbody.velocity.x, 0); if (jumpSFX != null) AudioSingleton.getSFXSource().PlayOneShot(jumpSFX); } //Blocks continous jump button if (!JumpKeyPressed) { jumpReleased = true; } //Apply Jump to player if (jumpT < jumpDuration) { jumpT += Time.deltaTime; float progress = (jumpDuration - jumpT) / jumpDuration; //|| jumpT < jumpDuration/2f if ((JumpKeyPressed) || b) { rigidbody.AddForce(new Vector2(0, jumpForce * progress)); } } else { b = false; } _isSwimming = inWater; } bool b; bool _isSwimming; public bool waterBoost; public bool canJump() { return jumpT >= jumpDuration && isGrounded && listenToInput && jumpReleased && !isSwimming && transform.childCount <= 0;//&& !GameManager.isPaused } public bool canBotJump() { return isGrounded || isSwimming || inWater; } //External Player Control Exposure public void Jump() { jumpT = 0; rigidbody.velocity = new Vector2(rigidbody.velocity.x, 0); b = true; AudioSingleton.getSFXSource().PlayOneShot(jumpSFX); } public void move(float input) { input = Mathf.Clamp(input, -1, 1); moveInput = input; } void OnLand() { // Debug.Log("Landed Like a boss!"); } void OnFly() { // Debug.Log("Hey look im flying"); } public float groundCheckerDist = 0.1f; public float groundCheckerHeighMultipler = 1f; public bool getGrounded() { //return (Physics2D.Linecast(transform.position, groundChecker.position, groundLayerMask)); Collider2D col = GetComponentInChildren(); return (Physics2D.BoxCast(col.bounds.center, new Vector2(col.bounds.size.x - (col.bounds.size.x / 5f), col.bounds.size.y * groundCheckerHeighMultipler), 0, Vector2.down, groundCheckerDist, groundLayerMask)); } void OnDrawGizmos() { Collider2D col = GetComponentInChildren(); Gizmos.DrawWireCube(transform.position, neighboursDetectorSize); Gizmos.color = Color.red; Gizmos.DrawWireCube(col.bounds.center - new Vector3(0, groundCheckerDist), new Vector2(col.bounds.size.x - (col.bounds.size.x / 5f), col.bounds.size.y * groundCheckerHeighMultipler)); } // public bool getInWater(){Collider2D col = GetComponentInChildren(); // return (Physics2D.BoxCast(col.bounds.center, new Vector2(col.bounds.size.x - (col.bounds.size.x / 5f), col.bounds.size.y), 0, Vector2.down, 0.1f, waterLayerMask)); // } } public static class AudioSingleton { private static AudioSource music; private static AudioSource sfx; public static AudioMixer mixer = Resources.Load("MasterMixer") as AudioMixer; public static AudioSource getMusicSource() { if (music == null) { GameObject go = new GameObject("Music Audio Source"); go.AddComponent(); music = go.GetComponent(); music.outputAudioMixerGroup = mixer.FindMatchingGroups("Music")[0]; } return music; } public static AudioSource getSFXSource() { //AudioMixer mixer = Resources.Load("MasterMixer") as AudioMixer; if (sfx == null) { GameObject go = new GameObject("SFX Audio Source"); go.AddComponent(); sfx = go.GetComponent(); Debug.Log("sfx : " + (sfx == null).ToString() + ", mixer: " + (mixer == null).ToString()); sfx.outputAudioMixerGroup = mixer.FindMatchingGroups("SFX")[0]; } return sfx; } }