public List <int> m_waitDestroyEntity = new List <int>(); //等待同步删除的实体 public PlayerCommandBase GetCommand(int frame) { //没有收到玩家输入复制玩家的最后一次输入 if (m_commandList.Count == 0) { PlayerCommandBase pb = GetForecast(frame); m_forecastList.Add(pb); return(pb); } else { for (int i = 0; i < m_commandList.Count; i++) { if (m_commandList[i].frame == frame) { m_lastInputCache = m_commandList[i]; m_commandList.RemoveAt(i); return(m_lastInputCache); } } PlayerCommandBase pb = GetForecast(frame); m_forecastList.Add(pb); return(pb); } }
public override bool EqualsCmd(PlayerCommandBase cmd) { //if (!(cmd is TestCommandComponent)) //{ // return false; //} //TestCommandComponent cc = cmd as TestCommandComponent; //if (id != cc.id) // return false; //if (frame != cc.frame) // return false; //if (isFire != cc.isFire) // return false; //if (element1 != cc.element1) // return false; //if (element2 != cc.element2) // return false; //if (!moveDir.Equals(cc.moveDir)) // return false; //if (!skillDir.Equals(cc.skillDir)) // return false; return(true); }
public override bool EqualsCmd(PlayerCommandBase cmd) { if (!(cmd is CommandComponent)) { return(false); } CommandComponent cc = cmd as CommandComponent; if (id != cc.id) { return(false); } if (frame != cc.frame) { return(false); } if (isFire != cc.isFire) { return(false); } if (!moveDir.Equals(cc.moveDir)) { return(false); } if (!skillDir.Equals(cc.skillDir)) { return(false); } return(true); }
void CheckCommandLogic(DebugMsg msg, EntityInfo entityInfo, ComponentInfo compInfo) { PlayerCommandRecordComponent pcrc = m_world.GetEntity(entityInfo.id).GetComp <PlayerCommandRecordComponent>(); PlayerCommandBase compLocal = pcrc.GetInputCahae(msg.frame); if (compLocal == null) { return; } compLocal.time = 0; string content = Serializer.Serialize(compLocal); if (!content.Equals(compInfo.content)) { string log = "error: frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + msg + " msg.id " + entityInfo.id + " comp:" + compInfo.m_compName + "\n remote:" + compInfo.content + "\n local:" + content + "\n"; Debug.LogWarning(log); string record = ""; for (int k = msg.frame; k > msg.frame - 10; k--) { PlayerCommandBase tmp = pcrc.GetInputCahae(k); record += "\nframe " + k + " c: " + Serializer.Serialize(tmp); } Debug.Log(record); } else { //Debug.Log(" confirm " + compInfo.content); } }
public PlayerCommandBase GetForecast(int frame) { Debug.Log("预测操作 id:" + Entity.ID + " frame " + frame); PlayerCommandBase cmd = m_lastInputCache.DeepCopy(); cmd.frame = frame; return(cmd); }
void ReceviceCommandMsg(T cmd, params object[] objs) { //Debug.Log("ReceviceCommandMsg frame " + cmd.frame + " frame " + Serializer.Serialize(cmd)); if (SyncDebugSystem.isDebug) { SyncDebugSystem.RecordMsg("cmd_commandComponent", cmd.frame, Serializer.Serialize(cmd)); } //立即返回确认消息 AffirmMsg amsg = new AffirmMsg(); amsg.index = cmd.frame; amsg.time = cmd.time; ProtocolAnalysisService.SendCommand(amsg); if (m_world.IsStart) { EntityBase entity = m_world.GetEntity(cmd.id); AddComp(entity); //自动添加记录组件 PlayerCommandRecordComponent pcrc = entity.GetComp <PlayerCommandRecordComponent>(ComponentType.PlayerCommandRecordComponent); PlayerCommandBase record = pcrc.GetInputCahae(cmd.frame); //判断和本地的预测有没有冲突 if (record == null || !record.EqualsCmd(cmd)) { pcrc.SetConflict(cmd.frame, true); } else { pcrc.SetConflict(cmd.frame, false); } if (pcrc.lastInputFrame < cmd.frame) { pcrc.lastInputFrame = cmd.frame; } pcrc.RecordCommand(cmd); //数据完整校验 if (cmd.frame != 0 && pcrc.GetAllMessage(cmd.frame) && !pcrc.GetAllMessage(cmd.frame - 1)) { ReSendMessage(cmd.frame - 1, cmd.id); } //Recalc(); } else { GameDataCacheComponent gdcc = m_world.GetSingletonComp <GameDataCacheComponent>(); gdcc.m_noExecuteCommandList.Add(cmd); } }
public PlayerCommandBase GetForecast(int frame) { //Debug.Log("预测操作 id:" + Entity.ID + " frame " + frame); PlayerCommandBase cmd = m_lastInputCache.DeepCopy(); //PlayerCommandBase cmd = new CommandComponent(); cmd.frame = frame; cmd.id = Entity.ID; return(cmd); }
public void RecordCommand(PlayerCommandBase cmd) { //Debug.Log("记录操作 id:" + cmd.id + " frame " + cmd.frame + " " + GetConflict(cmd.frame) + " ContainsKey " + m_inputCache.ContainsKey(cmd.frame)); if (m_inputCache.ContainsKey(cmd.frame)) { m_inputCache[cmd.frame] = cmd; } else { m_inputCache.Add(cmd.frame, cmd); } }
static void ReceviceSyncMsg(SyncSession session, T msg) { ConnectionComponent commandComp = session.m_connect; WorldBase world = session.m_connect.Entity.World; if (commandComp != null) { PlayerCommandBase comp = msg; comp.frame = msg.frame; if (msg.frame > world.FrameCount) { commandComp.m_commandList.Add(comp); //TODO 与预测一致不广播节约带宽 List <EntityBase> list = world.GetEntiyList(new string[] { "ConnectionComponent" }); for (int i = 0; i < list.Count; i++) { ConnectionComponent cp = list[i].GetComp <ConnectionComponent>(); if (cp != commandComp) { ProtocolAnalysisService.SendMsg(cp.m_session, msg); } } } else { //潜在的不同步威胁 Debug.Log("帧数落后 丢弃玩家操作 world.FrameCount: " + world.FrameCount + " msg frame:" + msg.frame); //发送给玩家自己 服务器给他预测的操作, for (int i = 0; i < commandComp.m_forecastList.Count; i++) { ProtocolAnalysisService.SendMsg(session, commandComp.m_forecastList[i]); } commandComp.m_forecastList.Clear(); //并且让这个玩家提前 commandComp.m_lastInputCache = comp; PursueMsg pmsg = new PursueMsg(); pmsg.frame = world.FrameCount; pmsg.advanceCount = 1; ProtocolAnalysisService.SendMsg(session, pmsg); } } }
void ReceviceCommandMsg(T cmd, params object[] objs) { if (m_world.IsStart) { //Debug.Log("ReceviceCommandMsg " + cmd.frame + " world " + m_world.FrameCount); PlayerCommandRecordComponent pcrc = m_world.GetEntity(cmd.id).GetComp <PlayerCommandRecordComponent>(); //判断帧数 if (m_world.FrameCount >= cmd.frame) { PlayerCommandBase input = null; if (m_world.FrameCount == cmd.frame) { input = pcrc.m_forecastInput; } else { input = pcrc.GetInputCahae(cmd.frame); } //替换原来的记录 pcrc.ReplaceCommand(cmd); //与本地预测做判断,如果不一致则需要重新演算 if (!cmd.EqualsCmd(input)) { Recalc(cmd.frame); } else { //清除以前的记录 m_world.ClearBefore(cmd.frame - 1); } } //存入缓存 else { //Debug.Log("存入缓存"); pcrc.m_serverCache.Add(cmd); } } else { //存入未执行命令列表 GameDataCacheComponent gdcc = m_world.GetSingletonComp <GameDataCacheComponent>(); gdcc.m_noExecuteCommandList.Add(cmd); } }
public void RecordCommand(PlayerCommandBase cmd) { //Debug.Log("记录操作 id:" + cmd.id + " frame " + cmd.frame); for (int i = 0; i < m_inputCache.Count; i++) { if (m_inputCache[i].frame == cmd.frame) { m_inputCache[i] = cmd; return; } } m_inputCache.Add(cmd); //本地没有记录,直接存入记录 }
public PlayerCommandBase m_lastInputCache = null; //玩家的最后一次输入 public PlayerCommandBase GetCommand(int frame) { //没有收到玩家输入复制玩家的最后一次输入 if (m_commandList.Count == 0) { return(m_lastInputCache); } else { m_lastInputCache = m_commandList[0]; m_commandList.RemoveAt(0); return(m_lastInputCache); } }
public override bool EqualsCmd(PlayerCommandBase cmd) { if (!(cmd is CommandComponent)) { return(false); } CommandComponent cc = cmd as CommandComponent; if (id != cc.id) { return(false); } if (frame != cc.frame) { return(false); } if (isFire != cc.isFire) { return(false); } if (isForward != cc.isForward) { return(false); } if (isBack != cc.isBack) { return(false); } if (isRight != cc.isRight) { return(false); } if (isLeft != cc.isLeft) { return(false); } return(true); }
static void ReceviceSyncMsg(SyncSession session, ChangeComponentMsg msg) { ConnectionComponent commandComp = session.m_connect; if (commandComp != null) { Type type = Type.GetType(msg.info.m_compName); if (type != null) { PlayerCommandBase comp = (PlayerCommandBase)deserializer.Deserialize(msg.info.m_compName, msg.info.content); commandComp.m_commandList.Add(comp); } } else { } }
public PlayerCommandBase GetForecastInput(int frame) { //取出上一帧的缓存赋值给下一帧做预测用 PlayerCommandBase record = GetInputCahae(lastInputFrame); //没有则取默认值 if (record == null) { record = m_defaultInput; } PlayerCommandBase cmd = record.DeepCopy(); cmd.frame = frame; cmd.id = Entity.ID; return(cmd); }
public void ReplaceCommand(PlayerCommandBase cmd) { for (int i = 0; i < m_inputCache.Count; i++) { if (m_inputCache[i].frame == cmd.frame) { m_inputCache[i] = cmd; //TODO 这里可能产生不同步 m_lastInput = cmd; //最后的输入也改变了 return; } } string content = ""; for (int i = 0; i < m_inputCache.Count; i++) { content += "id " + m_inputCache[i].id + " frame " + m_inputCache[i].frame + "\n"; } throw new Exception("ReplaceCommand faild ! id:->" + cmd.id + " frame:-> " + cmd.frame + " Count " + m_inputCache.Count + "\n" + content); }
void ReceviceSameCmdMsg(SameCommand cmd, params object[] objs) { if (m_world.IsStart) { EntityBase entity = m_world.GetEntity(cmd.id); AddComp(entity); //自动添加记录组件 PlayerCommandRecordComponent pcrc = entity.GetComp <PlayerCommandRecordComponent>(); PlayerCommandBase record = pcrc.GetInputCahae(cmd.frame - 1); if (record != null) { PlayerCommandBase sameCmd = record.DeepCopy(); sameCmd.frame = cmd.frame; ReceviceCommandMsg((T)sameCmd); } //缓存中没有数据,重新请求 else { ReSendMessage(cmd.frame, cmd.id); } } }
static void ReceviceSyncMsg(SyncSession session, T msg) { ConnectionComponent commandComp = session.m_connect; WorldBase world = session.m_entity.World; if (commandComp != null) { PlayerCommandBase comp = msg; comp.frame = msg.frame; if (msg.frame > world.FrameCount) { commandComp.m_commandList.Add(comp); //TODO 广播操作 } else { //TODO 潜在的不同步威胁 Debug.Log("帧数落后 丢弃玩家操作 world.FrameCount: " + world.FrameCount + " msg frame:" + msg.frame); commandComp.m_lastInputCache = comp; } } }
private void Update() { PlayerCommandBase cmd = GetCommand(); if (cmd != null) { if (disabled == cmd.IsValid()) { Disabled = !cmd.IsValid(); } } else { disabled = false; } if (!disabled) { bool pressed = CheckPressed(); Color targetColor = (pressed) ? pressColor : defaultColor; float targetScale = (pressed) ? 1.2f * defaultScale : defaultScale; img.color = Color.Lerp(img.color, targetColor, Time.deltaTime * lerpSpeed); transform.localScale = Vector3.Lerp(transform.localScale, Vector3.one * targetScale, Time.deltaTime * lerpSpeed); } }
//行動状態変数を初期化 public void Initialize(GameObject usingObj) { PlayerCommandBase[] command = new PlayerCommandBase[15]; waitingCommand = usingObj.AddComponent <WaitingCommand>(); runningCommand = usingObj.AddComponent <RunningCommand>(); slideRunningCommand = usingObj.AddComponent <SlideRunningCommand>(); jumpingFirstCommand = usingObj.AddComponent <JumpingFirstCommand>(); jumpingSecondCommand = usingObj.AddComponent <JumpingSecondCommand>(); jumpingWithUpToDownCommand = usingObj.AddComponent <JumpingWithUpToDownCommand>(); slideJumpingCommand = usingObj.AddComponent <SlideJumpingCommand>(); wallJumpingCommand = usingObj.AddComponent <WallJumpingCommand>(); cliffHoldingCommand = usingObj.AddComponent <CliffHoldingCommand>(); attackingFirstCommand = usingObj.AddComponent <AttackingFirstCommand>(); attackingSecondCommand = usingObj.AddComponent <AttackingSecondCommand>(); attackingThirdCommand = usingObj.AddComponent <AttackingThirdCommand>(); attackingInAirCommand = usingObj.AddComponent <AttackingInAirlialCommand>(); nockBackingCommand = usingObj.AddComponent <NockBackingCommand>(); dyingCommand = usingObj.AddComponent <DyingCommand>(); command[0] = waitingCommand; command[1] = runningCommand; command[2] = slideRunningCommand; command[3] = jumpingFirstCommand; command[4] = jumpingSecondCommand; command[5] = jumpingWithUpToDownCommand; command[6] = slideJumpingCommand; command[7] = wallJumpingCommand; command[8] = cliffHoldingCommand; command[9] = attackingFirstCommand; command[10] = attackingSecondCommand; command[11] = attackingThirdCommand; command[12] = attackingInAirCommand; command[13] = nockBackingCommand; command[14] = dyingCommand; for (int i = 0; i < command.Length; i++) { command[i].Initialize(usingObj); } PlayerStateEntry[] move = new PlayerStateEntry[3]; waiting = usingObj.AddComponent <Waiting>(); running = usingObj.AddComponent <Running>(); slideRunning = usingObj.AddComponent <SlideRunning>(); move[0] = waiting; move[1] = running; move[2] = slideRunning; for (int i = 0; i < move.Length; i++) { move[i].SubInitialize(usingObj); } PlayerStateEntry[] jump = new PlayerStateEntry[6]; jumpingFirst = usingObj.AddComponent <JumpingFirst>(); jumpingSecond = usingObj.AddComponent <JumpingSecond>(); jumpingWithUpToDown = usingObj.AddComponent <JumpingWithUpToDown>(); slideJumping = usingObj.AddComponent <SlideJumping>(); wallJumping = usingObj.AddComponent <WallJumping>(); cliffHolding = usingObj.AddComponent <CliffHolding>(); jump[0] = jumpingFirst; jump[1] = jumpingSecond; jump[2] = jumpingWithUpToDown; jump[3] = slideJumping; jump[4] = wallJumping; jump[5] = cliffHolding; for (int i = 0; i < jump.Length; i++) { jump[i].SubInitialize(usingObj); } PlayerStateEntry[] damage = new PlayerStateEntry[2]; nockBacking = usingObj.AddComponent <NockBacking>(); dying = usingObj.AddComponent <Dying>(); damage[0] = nockBacking; damage[1] = dying; for (int i = 0; i < damage.Length; i++) { damage[i].SubInitialize(usingObj); } PlayerStateEntry[] attack = new PlayerStateEntry[4]; attackingFirst = usingObj.AddComponent <AttackingFirst>(); attackingSecond = usingObj.AddComponent <AttackingSecond>();; attackingThird = usingObj.AddComponent <AttackingThird>();; attackingInAir = usingObj.AddComponent <AttackingInAirlial>();; attack[0] = attackingFirst; attack[1] = attackingSecond; attack[2] = attackingThird; attack[3] = attackingInAir; for (int i = 0; i < attack.Length; i++) { attack[i].SubInitialize(usingObj); } PlayerStateEntry[] main = new PlayerStateEntry[4]; moving = usingObj.AddComponent <PlayerMovingStateMachine>(); jumping = usingObj.AddComponent <PlayerJumpingStateMachine>(); attacking = usingObj.AddComponent <PlayerAttackingStateMachine>(); damaging = usingObj.AddComponent <PlayerDamagingStateMachine>(); main[0] = moving; main[1] = jumping; main[2] = attacking; main[3] = damaging; for (int i = 0; i < main.Length; i++) { main[i].SubInitialize(usingObj); } usingObj.GetComponent <PlayerStateMachine>().SubInitialize(usingObj); }
public void DebugLogic(DebugMsg msg) { if (msg.frame == m_world.FrameCount) { for (int i = 0; i < msg.infos.Count; i++) { if (m_world.GetEntityIsExist(msg.infos[i].id)) { EntityBase entity = m_world.GetEntity(msg.infos[i].id); for (int j = 0; j < msg.infos[i].infos.Count; j++) { ComponentBase compLocal = entity.GetComp(msg.infos[i].infos[j].m_compName); if (IsFilter(msg.infos[i].infos[j].m_compName)) { string content = Serializer.Serialize(compLocal); if (!content.Equals(msg.infos[i].infos[j].content)) { RecordSystemBase rsb = m_world.GetRecordSystemBase(msg.infos[i].infos[j].m_compName); string log = "error: frame" + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + entity.ID + " msg.id " + msg.infos[i].id + " comp:" + msg.infos[i].infos[j].m_compName + "\n remote:" + msg.infos[i].infos[j].content + "\n local:" + content + "\n"; Debug.LogWarning(log); rsb.PrintRecord(entity.ID); syncLog += log; //派发冲突 GlobalEvent.DispatchEvent(c_isConflict, msg.frame); } else { //Debug.Log("ReceviceDebugMsg correct! frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + entity.ID + " msg.id " + msg.infos[i].id + " comp:" + msg.infos[i].infos[j].m_compName + " content :"+ msg.infos[i].infos[j].content); } } } } else { string log = "error not find entity frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + msg.infos[i].id + "\n"; Debug.LogWarning(log); syncLog += log; } } } else if (msg.frame < m_world.FrameCount) { for (int i = 0; i < msg.infos.Count; i++) { if (m_world.GetEntityIsExist(msg.infos[i].id)) { EntityBase entity = m_world.GetEntity(msg.infos[i].id); for (int j = 0; j < msg.infos[i].infos.Count; j++) { if (msg.infos[i].infos[j].m_compName == "CommandComponent") { PlayerCommandRecordComponent pcrc = m_world.GetEntity(msg.infos[i].id).GetComp <PlayerCommandRecordComponent>(); PlayerCommandBase compLocal = pcrc.GetInputCahae(msg.frame); if (compLocal == null) { return; } compLocal.time = 0; string content = Serializer.Serialize(compLocal); if (!content.Equals(msg.infos[i].infos[j].content)) { string log = "error: frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + entity.ID + " msg.id " + msg.infos[i].id + " comp:" + msg.infos[i].infos[j].m_compName + "\n remote:" + msg.infos[i].infos[j].content + "\n local:" + content + "\n"; Debug.LogWarning(log); string record = ""; for (int k = msg.frame; k > msg.frame - 10; k--) { PlayerCommandBase tmp = pcrc.GetInputCahae(k); record += "\nframe " + k + " c: " + Serializer.Serialize(tmp); } Debug.Log(record); } else { //Debug.Log(" confirm " + msg.infos[i].infos[j].content); } } else { RecordSystemBase rsb = m_world.GetRecordSystemBase(msg.infos[i].infos[j].m_compName); ComponentBase compLocal = rsb.GetRecord(msg.infos[i].id, msg.frame); if (IsFilter(msg.infos[i].infos[j].m_compName)) { if (compLocal != null) { string content = Serializer.Serialize(compLocal); if (!content.Equals(msg.infos[i].infos[j].content)) { string log = "error: frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + entity.ID + " msg.id " + msg.infos[i].id + " comp:" + msg.infos[i].infos[j].m_compName + "\n remote:" + msg.infos[i].infos[j].content + "\n local:" + content + "\n"; Debug.LogWarning(log); rsb.PrintRecord(entity.ID); syncLog += log; } else { //Debug.Log("ReceviceDebugMsg correct! frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + entity.ID + " msg.id " + msg.infos[i].id + " comp:" + msg.infos[i].infos[j].m_compName + " content :" + msg.infos[i].infos[j].content); } //派发冲突 GlobalEvent.DispatchEvent(c_isConflict, msg.frame); } else { string log = "not find Record ->> frame:" + msg.frame + " id " + msg.infos[i].id + " compName: " + msg.infos[i].infos[j].m_compName + " currentframe: " + m_world.FrameCount + " content " + msg.infos[i].infos[j].content; //Debug.LogWarning(log); syncLog += log; } } } } } else { //string log = "error not find entity frame " + msg.frame + " currentFrame:" + m_world.FrameCount + " id:" + msg.infos[i].id + "\n"; //Debug.LogWarning(log); //syncLog += log; } } } else { string log = "服务器超前 msg:" + msg.frame + " m_world:" + m_world.FrameCount + "\n"; //Debug.LogWarning(log); syncLog += log; } }
public abstract bool EqualsCmd(PlayerCommandBase cmd);
void ReceviceCommandMsg(T cmd, params object[] objs) { //Debug.Log("ReceviceCommandMsg id" + cmd.id + " frame " + cmd.frame); if (m_world.IsStart) { PlayerCommandRecordComponent pcrc = m_world.GetEntity(cmd.id).GetComp <PlayerCommandRecordComponent>(); pcrc.lastInputFrame = cmd.frame; if (cmd.frame <= m_world.FrameCount) { //过去的命令 //如果与本地预测结果不一致,则重新演算 //不过要等到这一帧所有命令到齐才重计算 PlayerCommandBase record = pcrc.GetInputCahae(cmd.frame); if (record == null || !record.EqualsCmd(cmd)) { pcrc.m_isConflict = true; } else { pcrc.m_isConflict = false; } pcrc.RecordCommand(cmd); List <EntityBase> list = GetEntityList(); bool isAllMessage = false; bool isConflict = false; for (int i = 0; i < list.Count; i++) { PlayerCommandRecordComponent tmp = m_world.GetEntity(list[i].ID).GetComp <PlayerCommandRecordComponent>(); isAllMessage |= (tmp.lastInputFrame >= m_world.FrameCount); isConflict |= tmp.m_isConflict; } if (isAllMessage) { if (isConflict) { m_world.eventSystem.ClearCache(cmd.frame); //Debug.Log("消息不同重计算 "); Recalc(cmd.frame); } else { //此时派发确定性 m_world.eventSystem.DispatchCertainty(cmd.frame); } } if (isAllMessage) { } } else { pcrc.RecordCommand(cmd); } } else { //存入未执行命令列表 Debug.Log("存入未执行命令列表"); GameDataCacheComponent gdcc = m_world.GetSingletonComp <GameDataCacheComponent>(); //gdcc.m_noExecuteCommandList.Add(cmd); } }