You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.5 KiB
C#
152 lines
4.5 KiB
C#
3 weeks ago
|
namespace Fusion {
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using UnityEngine;
|
||
|
|
||
|
[StructLayout(LayoutKind.Explicit)]
|
||
|
[NetworkStructWeaved(WORDS + 4)]
|
||
|
public unsafe struct NetworkCCData : INetworkStruct {
|
||
|
public const int WORDS = NetworkTRSPData.WORDS + 4;
|
||
|
public const int SIZE = WORDS * 4;
|
||
|
|
||
|
[FieldOffset(0)]
|
||
|
public NetworkTRSPData TRSPData;
|
||
|
|
||
|
[FieldOffset((NetworkTRSPData.WORDS + 0) * Allocator.REPLICATE_WORD_SIZE)]
|
||
|
int _grounded;
|
||
|
|
||
|
[FieldOffset((NetworkTRSPData.WORDS + 1) * Allocator.REPLICATE_WORD_SIZE)]
|
||
|
Vector3Compressed _velocityData;
|
||
|
|
||
|
public bool Grounded {
|
||
|
get => _grounded == 1;
|
||
|
set => _grounded = (value ? 1 : 0);
|
||
|
}
|
||
|
|
||
|
public Vector3 Velocity {
|
||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
|
get => _velocityData;
|
||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
|
set => _velocityData = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DisallowMultipleComponent]
|
||
|
[RequireComponent(typeof(CharacterController))]
|
||
|
[NetworkBehaviourWeaved(NetworkCCData.WORDS)]
|
||
|
// ReSharper disable once CheckNamespace
|
||
|
public sealed unsafe class NetworkCharacterController : NetworkTRSP, INetworkTRSPTeleport, IBeforeAllTicks, IAfterAllTicks, IBeforeCopyPreviousState {
|
||
|
new ref NetworkCCData Data => ref ReinterpretState<NetworkCCData>();
|
||
|
|
||
|
[Header("Character Controller Settings")]
|
||
|
public float gravity = -20.0f;
|
||
|
public float jumpImpulse = 8.0f;
|
||
|
public float acceleration = 10.0f;
|
||
|
public float braking = 10.0f;
|
||
|
public float maxSpeed = 2.0f;
|
||
|
public float rotationSpeed = 15.0f;
|
||
|
|
||
|
Tick _initial;
|
||
|
CharacterController _controller;
|
||
|
|
||
|
public Vector3 Velocity {
|
||
|
get => Data.Velocity;
|
||
|
set => Data.Velocity = value;
|
||
|
}
|
||
|
|
||
|
public bool Grounded {
|
||
|
get => Data.Grounded;
|
||
|
set => Data.Grounded = value;
|
||
|
}
|
||
|
|
||
|
public void Teleport(Vector3? position = null, Quaternion? rotation = null) {
|
||
|
_controller.enabled = false;
|
||
|
NetworkTRSP.Teleport(this, transform, position, rotation);
|
||
|
_controller.enabled = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
public void Jump(bool ignoreGrounded = false, float? overrideImpulse = null) {
|
||
|
if (Data.Grounded || ignoreGrounded) {
|
||
|
var newVel = Data.Velocity;
|
||
|
newVel.y += overrideImpulse ?? jumpImpulse;
|
||
|
Data.Velocity = newVel;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Move(Vector3 direction) {
|
||
|
var deltaTime = Runner.DeltaTime;
|
||
|
var previousPos = transform.position;
|
||
|
var moveVelocity = Data.Velocity;
|
||
|
|
||
|
direction = direction.normalized;
|
||
|
|
||
|
if (Data.Grounded && moveVelocity.y < 0) {
|
||
|
moveVelocity.y = 0f;
|
||
|
}
|
||
|
|
||
|
moveVelocity.y += gravity * Runner.DeltaTime;
|
||
|
|
||
|
var horizontalVel = default(Vector3);
|
||
|
horizontalVel.x = moveVelocity.x;
|
||
|
horizontalVel.z = moveVelocity.z;
|
||
|
|
||
|
if (direction == default) {
|
||
|
horizontalVel = Vector3.Lerp(horizontalVel, default, braking * deltaTime);
|
||
|
} else {
|
||
|
horizontalVel = Vector3.ClampMagnitude(horizontalVel + direction * acceleration * deltaTime, maxSpeed);
|
||
|
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Runner.DeltaTime);
|
||
|
}
|
||
|
|
||
|
moveVelocity.x = horizontalVel.x;
|
||
|
moveVelocity.z = horizontalVel.z;
|
||
|
|
||
|
_controller.Move(moveVelocity * deltaTime);
|
||
|
|
||
|
Data.Velocity = (transform.position - previousPos) * Runner.TickRate;
|
||
|
Data.Grounded = _controller.isGrounded;
|
||
|
}
|
||
|
|
||
|
public override void Spawned() {
|
||
|
_initial = default;
|
||
|
TryGetComponent(out _controller);
|
||
|
CopyToBuffer();
|
||
|
}
|
||
|
|
||
|
public override void Render() {
|
||
|
NetworkTRSP.Render(this, transform, false, false, false, ref _initial);
|
||
|
}
|
||
|
|
||
|
void IBeforeAllTicks.BeforeAllTicks(bool resimulation, int tickCount) {
|
||
|
CopyToEngine();
|
||
|
}
|
||
|
|
||
|
void IAfterAllTicks.AfterAllTicks(bool resimulation, int tickCount) {
|
||
|
CopyToBuffer();
|
||
|
}
|
||
|
|
||
|
void IBeforeCopyPreviousState.BeforeCopyPreviousState() {
|
||
|
CopyToBuffer();
|
||
|
}
|
||
|
|
||
|
void Awake() {
|
||
|
TryGetComponent(out _controller);
|
||
|
}
|
||
|
|
||
|
void CopyToBuffer() {
|
||
|
Data.TRSPData.Position = transform.position;
|
||
|
Data.TRSPData.Rotation = transform.rotation;
|
||
|
}
|
||
|
|
||
|
void CopyToEngine() {
|
||
|
// CC must be disabled before resetting the transform state
|
||
|
_controller.enabled = false;
|
||
|
|
||
|
// set position and rotation
|
||
|
transform.SetPositionAndRotation(Data.TRSPData.Position, Data.TRSPData.Rotation);
|
||
|
|
||
|
// Re-enable CC
|
||
|
_controller.enabled = true;
|
||
|
}
|
||
|
}
|
||
|
}
|