private void OnActorAiState(SocketAsyncEventArgs args, byte[] bytes) { ActorAiState input = ActorAiState.Parser.ParseFrom(bytes); if (input.RoomId != RoomId) { return; // 不是自己房间的消息,略过 } if (input.AiCellIndexFrom == 0) { string msg = $"Actor position is lost!"; ServerRoomManager.Instance.Log("RoomLogic OnActorAiState Error - " + msg); ActorAiStateReply output2 = new ActorAiStateReply() { RoomId = input.RoomId, OwnerId = input.OwnerId, ActorId = input.ActorId, Ret = false, ErrMsg = msg, }; ServerRoomManager.Instance.SendMsg(args, ROOM_REPLY.ActorAiStateReply, output2.ToByteArray()); return; } // 更新单元Ai信息,在服务器的ActorBehaviour里保存一份 var ab = ActorManager.GetActor(input.ActorId); if (ab != null) { ab.AiState = input.AiState; ab.CellIndex = input.AiCellIndexFrom; ab.AiCellIndexTo = input.AiCellIndexTo; ab.AiTargetId = input.AiTargetId; ab.Orientation = input.Orientation; ab.AiDurationTime = input.AiDurationTime; ab.AiTotalTime = input.AiTotalTime; ab.AiStartTime = DateTime.Now; // 记录得到当前状态的时间, 在存盘的时候再记录一下时间, 把剩余时间保存起来 } // 注意: 有一种情况, 可能是ab并不存在,但是这条消息还是有用的,因为ActorRemoveReply消息里, 服务器已经把本单元删掉了, // 但是服务器仍然需要转发一条将单位状态设置为StateEnum.DIE的消息 ActorAiStateReply output = new ActorAiStateReply() { RoomId = input.RoomId, OwnerId = input.OwnerId, ActorId = input.ActorId, AiState = input.AiState, AiCellIndexFrom = input.AiCellIndexFrom, AiCellIndexTo = input.AiCellIndexTo, AiTargetId = input.AiTargetId, Orientation = input.Orientation, AiDurationTime = input.AiDurationTime, AiTotalTime = input.AiTotalTime, Ret = true, }; BroadcastMsg(ROOM_REPLY.ActorAiStateReply, output.ToByteArray()); }
private void OnActorAiStateReply(byte[] bytes) { ActorAiStateReply input = ActorAiStateReply.Parser.ParseFrom(bytes); if (input.ActorId != ActorId) { return; // 不是自己,略过 } if (!input.Ret) { return; } HexCell fromCell = GameRoomManager.Instance.HexmapHelper.GetCell(input.AiCellIndexFrom); Vector3 newPosition = Vector3.zero; HexCell targetCell = null; ActorVisualizer avTarget = null; if (AllActors.ContainsKey(input.AiTargetId)) { //如果目标是单位,优先用单位的[所在格子的]坐标作为目标点, 注意, 也不是目标点的实际坐标 avTarget = AllActors[input.AiTargetId]; targetCell = avTarget.HexUnit.Location; } else { targetCell = GameRoomManager.Instance.HexmapHelper.GetCell(input.AiCellIndexTo); } newPosition = targetCell.Position; StateEnum newAiState = (StateEnum)input.AiState; // 注: 在客户端: input.DurationTime是没有用的, 时间完全由 服务器端/AI端 控制 switch (CurrentAiState) { case StateEnum.GUARD: ShowShield(false); break; case StateEnum.HARVEST: ShowSliderHarvest(false); break; case StateEnum.FIGHT: break; } CurrentAiState = newAiState; TargetPosition = newPosition; TargetActorId = input.AiTargetId; TargetCellIndex = input.AiCellIndexTo; if (avTarget == null || avTarget.IsDead) { TargetActorId = 0; } AnimationState[] aniState = null; switch (CurrentAiState) { case StateEnum.IDLE: TargetPosition = CurrentPosition; GameRoomManager.Instance.HexmapHelper.Stop(input.ActorId); aniState = idleStates; break; case StateEnum.VANISH: //aniState = vanishStates; // vanishStates这个状态的动画不知道为什么不正确,这里只能继续沿用Die的最后一帧了 break; case StateEnum.DIE: GameRoomManager.Instance.HexmapHelper.Stop(input.ActorId); aniState = deathStates; break; case StateEnum.WALK: case StateEnum.WALKFIGHT: _listPath = GameRoomManager.Instance.HexmapHelper.DoMove(input.ActorId, input.AiCellIndexFrom, input.AiCellIndexTo); Debug.Log($"MSG: ActorAiState - {CurrentAiState} - From<{fromCell.coordinates.X},{fromCell.coordinates.X}> - To<{targetCell.coordinates.X},{targetCell.coordinates.Z}>"); //aniState = movementStates; aniState = runningStates; break; case StateEnum.FIGHT: GameRoomManager.Instance.HexmapHelper.Stop(input.ActorId); GameRoomManager.Instance.HexmapHelper.LookAt(input.ActorId, TargetPosition); ShowSliderBlood(); aniState = attackingStates; break; case StateEnum.DELAYFIGHT: ShowSliderBlood(); aniState = idleStates; // 先不播放战斗动画,过了AttackInternal的时间以后再通过ActorPlayAni消息来播 break; case StateEnum.GUARD: ShowShield(); GameRoomManager.Instance.HexmapHelper.Stop(input.ActorId); aniState = idleStates; break; case StateEnum.HARVEST: ShowSliderHarvest(true, input.AiDurationTime, input.AiTotalTime); aniState = harvestStates; break; case StateEnum.NONE: aniState = idleStates; break; } PlayAnimation(aniState); }