netcode-02/Assets/Fox/Scripts/FoxMovement.cs
2022-07-01 09:54:51 +08:00

134 lines
3.7 KiB
C#

using Unity.Netcode;
using UnityEngine;
[RequireComponent(typeof(NetworkObject))]
public class PlayerControl : NetworkBehaviour
{
[SerializeField]
private float walkSpeed = 3.5f;
[SerializeField]
private float runSpeedOffset = 2.0f;
[SerializeField]
private float rotationSpeed = 3.5f;
[SerializeField]
private Vector2 defaultInitialPositionOnPlane = new Vector2(-4, 4);
[SerializeField]
private NetworkVariable<Vector3> networkPositionDirection = new NetworkVariable<Vector3>();
[SerializeField]
private NetworkVariable<Vector3> networkRotationDirection = new NetworkVariable<Vector3>();
[SerializeField]
private NetworkVariable<PlayerState> networkPlayerState = new NetworkVariable<PlayerState>();
private CharacterController characterController;
// client caches positions
private Vector3 oldInputPosition = Vector3.zero;
private Vector3 oldInputRotation = Vector3.zero;
private PlayerState oldPlayerState = PlayerState.Idle;
private Animator animator;
private void Awake()
{
characterController = GetComponent<CharacterController>();
animator = GetComponent<Animator>();
}
void Start()
{
if (IsClient && IsOwner)
{
transform.position = new Vector3(Random.Range(defaultInitialPositionOnPlane.x, defaultInitialPositionOnPlane.y), 0,
Random.Range(defaultInitialPositionOnPlane.x, defaultInitialPositionOnPlane.y));
}
}
void Update()
{
if (IsClient && IsOwner)
{
ClientInput();
}
ClientMoveAndRotate();
ClientVisuals();
}
private void ClientMoveAndRotate()
{
if (networkPositionDirection.Value != Vector3.zero)
{
characterController.SimpleMove(networkPositionDirection.Value);
}
if (networkRotationDirection.Value != Vector3.zero)
{
transform.Rotate(networkRotationDirection.Value, Space.World);
}
}
private void ClientVisuals()
{
if (oldPlayerState != networkPlayerState.Value)
{
oldPlayerState = networkPlayerState.Value;
animator.SetTrigger($"{networkPlayerState.Value}");
}
}
private void ClientInput()
{
// left & right rotation
Vector3 inputRotation = new Vector3(0, Input.GetAxis("Horizontal"), 0);
// forward & backward direction
Vector3 direction = transform.TransformDirection(Vector3.forward);
float forwardInput = Input.GetAxis("Vertical");
Vector3 inputPosition = direction * forwardInput;
// change animation states
if (forwardInput == 0)
UpdatePlayerStateServerRpc(PlayerState.Idle);
else if (!ActiveRunningActionKey() && forwardInput > 0 && forwardInput <= 1)
UpdatePlayerStateServerRpc(PlayerState.Walk);
else if (ActiveRunningActionKey() && forwardInput > 0 && forwardInput <= 1)
{
inputPosition = direction * runSpeedOffset;
UpdatePlayerStateServerRpc(PlayerState.Run);
}
else if (forwardInput < 0)
UpdatePlayerStateServerRpc(PlayerState.ReverseWalk);
// let server know about position and rotation client changes
if (oldInputPosition != inputPosition ||
oldInputRotation != inputRotation)
{
oldInputPosition = inputPosition;
UpdateClientPositionAndRotationServerRpc(inputPosition * walkSpeed, inputRotation * rotationSpeed);
}
}
private static bool ActiveRunningActionKey()
{
return Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
}
[ServerRpc]
public void UpdateClientPositionAndRotationServerRpc(Vector3 newPosition, Vector3 newRotation)
{
networkPositionDirection.Value = newPosition;
networkRotationDirection.Value = newRotation;
}
[ServerRpc]
public void UpdatePlayerStateServerRpc(PlayerState state)
{
networkPlayerState.Value = state;
}
}