111 lines
3.3 KiB
C#
111 lines
3.3 KiB
C#
using System;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
public struct PlayerImpactState : INetworkSerializable, IEquatable<PlayerImpactState>
|
|
{
|
|
public uint Sequence;
|
|
public Vector3 Impulse;
|
|
public float ShakeAmplitude;
|
|
public float ShakeDuration;
|
|
public float ShakeFrequency;
|
|
public float ShakeSeed;
|
|
|
|
public PlayerImpactState(
|
|
uint sequence,
|
|
Vector3 impulse,
|
|
float shakeAmplitude,
|
|
float shakeDuration,
|
|
float shakeFrequency,
|
|
float shakeSeed)
|
|
{
|
|
Sequence = sequence;
|
|
Impulse = impulse;
|
|
ShakeAmplitude = shakeAmplitude;
|
|
ShakeDuration = shakeDuration;
|
|
ShakeFrequency = shakeFrequency;
|
|
ShakeSeed = shakeSeed;
|
|
}
|
|
|
|
public void NetworkSerialize<T>(BufferSerializer<T> serializer)
|
|
where T : IReaderWriter
|
|
{
|
|
serializer.SerializeValue(ref Sequence);
|
|
serializer.SerializeValue(ref Impulse);
|
|
serializer.SerializeValue(ref ShakeAmplitude);
|
|
serializer.SerializeValue(ref ShakeDuration);
|
|
serializer.SerializeValue(ref ShakeFrequency);
|
|
serializer.SerializeValue(ref ShakeSeed);
|
|
}
|
|
|
|
public bool Equals(PlayerImpactState other) =>
|
|
Sequence == other.Sequence && Impulse == other.Impulse &&
|
|
ShakeAmplitude.Equals(other.ShakeAmplitude) &&
|
|
ShakeDuration.Equals(other.ShakeDuration) &&
|
|
ShakeFrequency.Equals(other.ShakeFrequency) &&
|
|
ShakeSeed.Equals(other.ShakeSeed);
|
|
}
|
|
|
|
[DisallowMultipleComponent]
|
|
public sealed class PlayerImpactController : NetworkBehaviour, IPlayerSystem
|
|
{
|
|
private readonly NetworkVariable<PlayerImpactState> impactState = new(
|
|
default,
|
|
NetworkVariableReadPermission.Everyone,
|
|
NetworkVariableWritePermission.Server);
|
|
|
|
private PlayerController movement;
|
|
private PlayerCameraShakeController cameraShake;
|
|
|
|
public uint LastImpactSequence => impactState.Value.Sequence;
|
|
public event Action<PlayerImpactState> ImpactApplied;
|
|
|
|
public void Initialize(PlayerFacade facade)
|
|
{
|
|
movement = GetComponent<PlayerController>();
|
|
cameraShake = GetComponent<PlayerCameraShakeController>();
|
|
}
|
|
|
|
public override void OnNetworkSpawn()
|
|
{
|
|
impactState.OnValueChanged += HandleImpactChanged;
|
|
}
|
|
|
|
public override void OnNetworkDespawn()
|
|
{
|
|
impactState.OnValueChanged -= HandleImpactChanged;
|
|
}
|
|
|
|
public bool ApplyImpactOnServer(Vector3 impulse, ShockwaveZone zone)
|
|
{
|
|
if (!IsServer || !IsSpawned)
|
|
return false;
|
|
|
|
impactState.Value = new PlayerImpactState(
|
|
impactState.Value.Sequence + 1,
|
|
impulse,
|
|
zone.CameraShakeAmplitude,
|
|
zone.CameraShakeDuration,
|
|
zone.CameraShakeFrequency,
|
|
UnityEngine.Random.Range(0f, 1000f));
|
|
return true;
|
|
}
|
|
|
|
private void HandleImpactChanged(PlayerImpactState previous, PlayerImpactState current)
|
|
{
|
|
if (current.Sequence == 0 || current.Sequence == previous.Sequence)
|
|
return;
|
|
|
|
ImpactApplied?.Invoke(current);
|
|
if (!IsOwner)
|
|
return;
|
|
|
|
movement?.AddImpulse(current.Impulse);
|
|
cameraShake?.PlayShake(
|
|
current.ShakeAmplitude,
|
|
current.ShakeDuration,
|
|
current.ShakeFrequency,
|
|
current.ShakeSeed);
|
|
}
|
|
}
|