您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

227 行
8.2 KiB

using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
public class PlayerModuleClient
{
public bool PlayerStateReady
{
get { return m_LocalPlayer.playerState != null; }
}
public bool IsControllingEntity
{
get { return PlayerStateReady && m_LocalPlayer.playerState.controlledEntity != Entity.Null; }
}
public void GetBufferedCommandsTick(out int firstTick, out int lastTick)
{
firstTick = m_LocalPlayer.commandBuffer.FirstTick();
lastTick = m_LocalPlayer.commandBuffer.LastTick();
}
public PlayerModuleClient(GameWorld world)
{
m_world = world;
m_HandlePlayerCameraControlSpawn = m_world.GetECSWorld().CreateManager<HandlePlayerCameraControlSpawn>(m_world);
m_UpdatePlayerCameras = m_world.GetECSWorld().CreateManager<UpdatePlayerCameras>(m_world);
m_ResolvePlayerReference = m_world.GetECSWorld().CreateManager<ResolvePlayerReference>(m_world);
m_UpdateServerEntityComponent = m_world.GetECSWorld().CreateManager<UpdateServerEntityComponent>(m_world);
}
public void Shutdown()
{
m_world.GetECSWorld().DestroyManager(m_HandlePlayerCameraControlSpawn);
m_world.GetECSWorld().DestroyManager(m_UpdatePlayerCameras);
m_world.GetECSWorld().DestroyManager(m_ResolvePlayerReference);
m_world.GetECSWorld().DestroyManager(m_UpdateServerEntityComponent);
if(m_LocalPlayer != null)
m_world.RequestDespawn(m_LocalPlayer.gameObject);
}
public LocalPlayer RegisterLocalPlayer(int playerId, NetworkClient networkClient)
{
var prefab = Resources.Load<LocalPlayer>("Prefabs/LocalPlayer");
m_LocalPlayer = m_world.Spawn<LocalPlayer>(prefab.gameObject);
m_LocalPlayer.playerId = playerId;
m_LocalPlayer.networkClient = networkClient;
m_LocalPlayer.command.lookPitch = 90;
m_ResolvePlayerReference.SetLocalPlayer(m_LocalPlayer);
return m_LocalPlayer;
}
public void SampleInput(bool userInputEnabled, float deltaTime, int renderTick)
{
// Only sample input when cursor is locked to avoid affecting multiple clients running on same machine (TODO: find better handling of selected window)
if (userInputEnabled)
Game.inputSystem.AccumulateInput(ref m_LocalPlayer.command, deltaTime);
if (m_debugMove.IntValue == 1)
{
m_LocalPlayer.command.moveMagnitude = 1;
m_LocalPlayer.command.lookYaw += 70 * deltaTime;
}
if (m_debugMove.IntValue == 2)
{
m_debugMoveDuration += deltaTime;
var fireDuration = 2.0f;
var jumpDuration = 1.0f;
var maxTurn = 70.0f;
if (m_debugMoveDuration > m_debugMovePhaseDuration)
{
m_debugMoveDuration = 0;
m_debugMovePhaseDuration = 4 + 2*Random.value;
m_debugMoveTurnSpeed = maxTurn *0.9f + Random.value * maxTurn * 0.1f;
m_debugMoveMag = Random.value > 0.5f ? 1.0f : 0.0f;
}
m_LocalPlayer.command.moveMagnitude = m_debugMoveMag;
m_LocalPlayer.command.lookYaw += m_debugMoveTurnSpeed * deltaTime;
m_LocalPlayer.command.lookYaw = m_LocalPlayer.command.lookYaw % 360;
while (m_LocalPlayer.command.lookYaw < 0.0f) m_LocalPlayer.command.lookYaw += 360.0f;
m_LocalPlayer.command.primaryFire = m_debugMoveDuration < fireDuration;
m_LocalPlayer.command.jump = m_debugMoveDuration < jumpDuration;
}
m_LocalPlayer.command.renderTick = renderTick;
}
public void ResetInput(bool userInputEnabled)
{
// Clear keys and resample to make sure released keys gets detected.
// Pass in 0 as deltaTime to make mouse input and view stick do nothing
Game.inputSystem.ClearInput(ref m_LocalPlayer.command);
if (userInputEnabled)
Game.inputSystem.AccumulateInput(ref m_LocalPlayer.command, 0.0f);
}
public void HandleCommandReset()
{
if (m_LocalPlayer.playerState == null || m_LocalPlayer.playerState.controlledEntity == Entity.Null)
return;
var commandComponent = m_world.GetEntityManager()
.GetComponentObject<UserCommandComponent>(m_LocalPlayer.playerState.controlledEntity);
if (commandComponent.resetCommandTick > commandComponent.lastResetCommandTick)
{
commandComponent.lastResetCommandTick = commandComponent.resetCommandTick;
m_LocalPlayer.command.lookYaw = commandComponent.resetCommandLookYaw;
m_LocalPlayer.command.lookPitch = commandComponent.resetCommandLookPitch;
}
}
public void ResolveReferenceFromLocalPlayerToPlayer()
{
if (m_LocalPlayer.playerState == null)
m_ResolvePlayerReference.Update();
}
public void HandleControlledEntityChanged()
{
m_UpdateServerEntityComponent.Update();
}
public void StoreCommand(int tick)
{
if (m_LocalPlayer.playerState == null)
return;
m_LocalPlayer.command.checkTick = tick;
var lastBufferTick = m_LocalPlayer.commandBuffer.LastTick();
if (tick != lastBufferTick && tick != lastBufferTick + 1)
{
m_LocalPlayer.commandBuffer.Clear();
GameDebug.Log(string.Format("Trying to store tick:{0} but last buffer tick is:{1}. Clearing buffer", tick, lastBufferTick));
}
if (tick == lastBufferTick)
m_LocalPlayer.commandBuffer.Set(ref m_LocalPlayer.command, tick);
else
m_LocalPlayer.commandBuffer.Add(ref m_LocalPlayer.command, tick);
#if UNITY_EDITOR
StateHistory.SetCommand(tick, ref m_LocalPlayer.command);
#endif
}
// Fetches command for a tick and stores it in the UserCommandComponent
public void RetrieveCommand(int tick)
{
GameDebug.Assert(m_LocalPlayer.playerState != null, "No player state set");
if (m_LocalPlayer.controlledEntity == Entity.Null)
return;
var userCommand = m_world.GetEntityManager().GetComponentObject<UserCommandComponent>(m_LocalPlayer.controlledEntity);
GameDebug.Assert(userCommand != null);
var command = UserCommand.defaultCommand;
var found = m_LocalPlayer.commandBuffer.TryGetValue(tick, ref command);
GameDebug.Assert(found, "Failed to find command for tick:{0}",tick);
// Normally we can expect commands to be present, but if client has done hardcatchup commands might not have been generated yet
// so we just use the defaultCommand
userCommand.prevCommand = userCommand.command;
userCommand.command = command;
}
public bool HasCommands(int firstTick, int lastTick)
{
var hasCommands = m_LocalPlayer.commandBuffer.FirstTick() <= firstTick &&
m_LocalPlayer.commandBuffer.LastTick() >= lastTick;
return hasCommands;
}
public void SendCommand(int tick)
{
if (m_LocalPlayer.playerState == null)
return;
var command = UserCommand.defaultCommand;
var commandValid = m_LocalPlayer.commandBuffer.TryGetValue(tick, ref command);
if (commandValid)
{
m_LocalPlayer.networkClient.QueueCommand(tick, (ref NetworkWriter writer) =>
{
command.Serialize(ref writer, null);
});
}
}
public void HandleSpawn()
{
m_HandlePlayerCameraControlSpawn.Update();
}
public void CameraUpdate()
{
m_UpdatePlayerCameras.Update();
}
readonly GameWorld m_world;
LocalPlayer m_LocalPlayer;
readonly HandlePlayerCameraControlSpawn m_HandlePlayerCameraControlSpawn;
readonly UpdatePlayerCameras m_UpdatePlayerCameras;
readonly ResolvePlayerReference m_ResolvePlayerReference;
readonly UpdateServerEntityComponent m_UpdateServerEntityComponent;
[ConfigVar(Name = "debugmove", DefaultValue = "0", Description = "Should client perform debug movement")]
static ConfigVar m_debugMove;
float m_debugMoveDuration;
float m_debugMovePhaseDuration;
float m_debugMoveTurnSpeed;
float m_debugMoveMag;
}