Files
Test-Multiplayer/Assets/Scripts/CharacterMovement.cs
pelpanagiotis 329b7d3183 First Commit
2025-12-21 18:31:02 +02:00

141 lines
3.9 KiB
C#

using UnityEngine;
using Mirror;
public class CharacterMovement : NetworkBehaviour
{
Animator animator;
int isWalkingHash;
int isRunningHash;
PlayerInput input;
Vector2 currentMovement;
bool movementPressed;
bool runPressed;
// track last sent state to avoid network spam
bool lastSentWalking;
bool lastSentRunning;
void Awake()
{
input = new PlayerInput();
input.CharacterControls.Movement.performed += ctx =>
{
currentMovement = ctx.ReadValue<Vector2>();
movementPressed = currentMovement.x != 0 || currentMovement.y != 0;
};
input.CharacterControls.Run.performed += ctx => runPressed = ctx.ReadValueAsButton();
}
void Start()
{
animator = GetComponent<Animator>();
isWalkingHash = Animator.StringToHash("isWalking");
isRunningHash = Animator.StringToHash("isRunning");
}
// Only the local player should drive input/movement
void Update()
{
if (!isLocalPlayer) return;
HandleMovement();
HandleRotation();
}
void HandleRotation()
{
Vector3 currentPosition = transform.position;
Vector3 newPosition = new Vector3(currentMovement.x, 0, currentMovement.y);
Vector3 positionToLookAt = currentPosition + newPosition;
transform.LookAt(positionToLookAt);
}
void HandleMovement()
{
bool isRunning = animator.GetBool(isRunningHash);
bool isWalking = animator.GetBool(isWalkingHash);
if (movementPressed && !isWalking)
{
animator.SetBool(isWalkingHash, true);
isWalking = true;
}
if (!movementPressed && isWalking)
{
animator.SetBool(isWalkingHash, false);
isWalking = false;
}
if ((movementPressed && runPressed) && !isRunning)
{
animator.SetBool(isRunningHash, true);
isRunning = true;
}
if ((!movementPressed || !runPressed) && isRunning)
{
animator.SetBool(isRunningHash, false);
isRunning = false;
}
// send animator state to server only when changed
if (isWalking != lastSentWalking || isRunning != lastSentRunning)
{
lastSentWalking = isWalking;
lastSentRunning = isRunning;
CmdSendAnimationState(isWalking, isRunning);
}
// movement translation (local)
// keep your movement application here (velocity, CharacterController, Rigidbody.ApplyForce, etc.)
// Example simple translation (adjust speed as needed):
float speed = isRunning ? 6f : 3f;
Vector3 move = new Vector3(currentMovement.x, 0, currentMovement.y) * speed * Time.deltaTime;
transform.position += move;
}
public override void OnStartLocalPlayer()
{
Debug.Log("Local player started: " + netId);
input.CharacterControls.Enable();
}
public override void OnStopLocalPlayer()
{
input.CharacterControls.Disable();
}
// Called on the server when client issues the command
[Command]
void CmdSendAnimationState(bool walking, bool running)
{
// update server-side animator if present
if (animator == null) animator = GetComponent<Animator>();
if (animator != null)
{
animator.SetBool(isWalkingHash, walking);
animator.SetBool(isRunningHash, running);
}
// broadcast to all clients
RpcUpdateAnimationState(walking, running);
}
// Executed on all clients to apply animator changes
[ClientRpc]
void RpcUpdateAnimationState(bool walking, bool running)
{
if (animator == null) animator = GetComponent<Animator>();
if (animator == null) return;
animator.SetBool(isWalkingHash, walking);
animator.SetBool(isRunningHash, running);
}
}