public bool IsEnemyInRange(ActorVisualizer avEnemy)
        {
            if (avEnemy == null)
            {
                return(false);
            }
            List <HexCell> cellsInRange = GameRoomManager.Instance.HexmapHelper.GetCellsInRange(HexUnit.Location, (int)ShootingRange);

            if (cellsInRange.Contains(avEnemy.HexUnit.Location))
            {
                return(true);
            }

            return(false);
        }
        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);
        }