public void LocalPlayerWalkToDestination(Vector3 targetPos, Task relateTask = null)
        {
            Actor player = Game.GetInstance().GetLocalPlayer();

            if (player == null)
            {
                return;
            }

            targetPos.y = RoleHelp.GetHeightInScene(player.ActorId, targetPos.x, targetPos.z);
            targetPos   = InstanceHelper.ClampInWalkableRange(targetPos, 10);

            // 判断是否可到达
            XNavMeshPath walkMeshPath = new XNavMeshPath();

            XNavMesh.CalculatePath(player.transform.position, targetPos, xc.Dungeon.LevelManager.GetInstance().AreaExclude, walkMeshPath);
            if (walkMeshPath.status != XNavMeshPathStatus.PathComplete)
            {
                // 如果通过任务导航寻路,且在新手副本的不可到达区域,则直接飞过去,以免因为配置错误而导致卡死
                if (relateTask != null && SceneHelp.Instance.CurSceneID == GameConstHelper.GetUint("GAME_BORN_DUNGEON"))
                {
                    GameDebug.LogWarning(DBConstText.GetText("MAP_POS_CAN_NOT_REACH") + ",该场景是新手场景,直接瞬移过去");
                    player.MoveCtrl.SendFly(targetPos);
                    player.SetPosition(targetPos);
                }
                else
                {
                    UINotice.Instance.ShowMessage(DBConstText.GetText("MAP_POS_CAN_NOT_REACH"));
                }
                return;
            }

            InstanceManager.Instance.IsAutoFighting = false;

            mPathWalker.WalkTo(targetPos);
            //player.MoveCtrl.TryWalkTo(targetPos);

            /*
             * uint instanceType = InstanceManager.Instance.InstanceType;
             *
             * if (instanceType == GameConst.WAR_TYPE_WILD || instanceType == GameConst.WAR_TYPE_HOLE || instanceType == GameConst.WAR_SUBTYPE_WILD_PUB || instanceType == GameConst.WAR_TYPE_MULTI)
             * {
             *  if(mPathWalker == null)
             *  {
             *      return;
             *  }
             *
             *  mPathWalker.WalkTo(targetPos);
             * }
             * else
             * {
             *  player.MoveCtrl.TryWalkTo(targetPos);
             * }*/

            TaskNavigationActive(true);
            IsNavigating = true;
        }
Exemple #2
0
        /// <summary>
        /// 响应点击地面的消息
        /// </summary>
        /// <param name="ent"></param>
        void OnClickCollision(CEventBaseArgs ent)
        {
            Actor local_player = Game.Instance.GetLocalPlayer();

            if (local_player == null)
            {
                return;
            }

            if (GameInput.Instance.GetEnableInput() == false || UIInputEvent.TouchedUI()) /* || InstanceManager.Instance.IsAutoFighting == true*/
            {
                return;
            }

            Vector3 hitPos = (Vector3)ent.arg;

            XNavMeshHit nesrestHit;

            if (XNavMesh.SamplePosition(hitPos, out nesrestHit, 5.0f, LevelManager.GetInstance().AreaExclude))
            {
                hitPos = nesrestHit.position;
            }

            StopLocalPlayerWalkCoroutine();
            mLocalPlayerWalkCoroutine = SafeCoroutine.CoroutineManager.StartCoroutine(LocalPlayerWalkCoroutine(hitPos));

            if (m_ArrowEffectTemp == null)
            {
                MainGame.HeartBehavior.StartCoroutine(LoadEffect(m_ClickEffectPath, hitPos));
            }
            //EffectManager.GetInstance().GetEffectEmitter(effect_path).CreateInstance(x => OnEffectResLoad(x, ));
            else
            {
                OnEffectResLoad(m_ArrowEffectTemp, hitPos);
            }
        }
Exemple #3
0
        /// <summary>
        /// 移动固定的位置
        /// </summary>
        /// <param name="offset">移动的偏移数值</param>
        /// <param name="on_ground">移动时是否贴近地面</param>
        /// <param name="slider">移动时是否沿着边界滑动</param>
        public void Move(Vector3 offset, bool on_ground, bool slider = true)
        {
//             MoveAgent(offset, on_ground, slider);
//             return;

            if (offset == Vector3.zero || mOwner.DisableMoveState)
            {
                return;
            }

            move_data.pos = new PkgNwarPos();

            // 减少Trans.position 这样的调用,会显著影响性能
            Vector3 ownerPos = mOwnerTrans.position;

            // 当移动不贴近地面(浮空等)时,需要先计算贴近地面的高度,不然NavMesh的碰撞检测可能检测不到
            if (on_ground == false)
            {
                float height = RoleHelp.GetHeightInScene(mOwner.ActorId, ownerPos.x, ownerPos.z);
                ownerPos.y = height;
            }

            Vector3 origin = ownerPos;        // 碰撞检测的起点
            Vector3 newPos = origin + offset; // 移动后的新位置

            Vector3 move     = offset;        // 偏移量
            float   offset_y = move.y;        // 记录原有的高度偏移

            move.y = 0;                       // 碰撞检测时将高度偏移设置为0

            bool touchEdge = false;           // 已经触碰到边界

            bool is_localplayer = mOwner.IsLocalPlayer;

            bool collide_check = true;
            bool is_monster    = mOwner.IsMonster();//怪物不进行碰撞检测

            if (is_monster)
            {
                collide_check = false;
            }
            else
            {
                collide_check = true;
            }

            if (collide_check)
            {
                Vector3     final_move = move;
                XNavMeshHit hit;
                if (XNavMesh.Raycast(origin, origin + move * (1.0f + Radius / move.magnitude), out hit, LevelManager.GetInstance().AreaExclude))
                {
                    touchEdge = true;

                    if (slider)// 需要沿着边界滑动时
                    {
                        float sameDir = Vector3.Dot(hit.normal, final_move);
                        if (sameDir > 0)// 法线与移动方向相同,说明角色在边界外
                        {
                            final_move.y = offset_y;
                            newPos       = origin + final_move;
                        }
                        else
                        {
                            if (hit.normal == Vector3.zero)// NavMesh获得的法线数值可能为0
                            {
                                Debug.DrawLine(origin, origin + final_move, Color.yellow, 5.0f);

                                final_move.y = offset_y;
                                newPos       = origin + final_move;
                                //final_move = Vector3.zero;
                                //newPos = origin;
                            }
                            else
                            {
                                // 碰到边界进行滑动
                                Vector3 tanget = Vector3.Cross(Vector3.up, hit.normal);
                                final_move = tanget * Vector3.Dot(tanget, final_move);
                                float sMoveLen = final_move.magnitude;
                                if (sMoveLen < DBActor.MinDisToGround)// 移动方向垂直于法线
                                {
                                    final_move = Vector3.zero;
                                    newPos     = origin;
                                }
                                else
                                {
                                    // 沿着切线方向再次做检测,以免滑动的时候移动到另一个边界外
                                    if (XNavMesh.Raycast(origin, origin + final_move * (1.0f + Radius / sMoveLen), out hit, LevelManager.GetInstance().AreaExclude))
                                    {
                                        final_move = Vector3.zero;
                                        newPos     = origin;
                                    }
                                    else
                                    {
                                        final_move.y = offset_y;
                                        newPos       = origin + final_move;
                                    }
                                }
                            }
                        }
                    }
                    else// 不滑动,则直接移动到碰撞点
                    {
                        Vector3 radius_pos = PhysicsHelp.BoundaryHitPos(origin, hit.position);
                        newPos.x = radius_pos.x;
                        newPos.z = radius_pos.z;
                    }
                }
            }

            float terrain_height = RoleHelp.GetHeightInScene(mOwner.ActorId, newPos.x, newPos.z);

            if (newPos.y < terrain_height + DBActor.MinDisToGround)// 如果当前位置已经贴近地面,则设置m_IsGround为true
            {
                m_IsGround = true;
                newPos.y   = terrain_height;
            }
            else
            {
                if (on_ground || touchEdge) // 如果角色已经触碰到边界,则让其掉到地上
                {
                    newPos.y   = terrain_height;
                    m_IsGround = true;
                }
                else
                {
                    m_IsGround = false;
                }
            }

            // 在多人副本、野外地图中,本地玩家碰到障碍物的时候需要通知服务端
            if (is_localplayer && slider)
            {
                if (touchEdge)
                {
                    m_IsTouchEdge = true;

                    Vector3 totalMove = newPos - origin;
                    totalMove.y = 0;
                    Vector3 moveDir = totalMove.normalized;

                    move_data.id     = mOwner.UID.obj_idx;
                    move_data.pos.px = (int)(origin.x * 100.0f);
                    move_data.pos.py = (int)(origin.z * 100.0f);
                    move_data.dir    = Maths.Util.VectorToAngle(moveDir);

                    float   totalMoveLen = totalMove.magnitude;
                    Vector3 xz_offset    = offset;
                    xz_offset.y = 0;
                    float ortMoveLen = xz_offset.magnitude;
                    if (totalMoveLen > 0 && ortMoveLen > 0)
                    {
                        move_data.speed = (uint)(mOwner.MoveSpeed * (totalMoveLen / ortMoveLen) * 100);
                    }
                    else
                    {
                        move_data.speed = 0;
                    }

                    // 数据发生变化时才发送滑动协议
                    if (!mSliderData.Equal(move_data))
                    {
                        mSliderData.Assign(move_data);

                        slider_data.slide = move_data;
                        NetClient.GetCrossClient().SendData <C2SNwarSlide>(NetMsg.MSG_NWAR_SLIDE, slider_data);
                    }
                }
                // 当滑动结束时,需要同步一次方向和位置
                else if (m_IsTouchEdge)
                {
                    m_IsTouchEdge = false;

                    Vector3 totalMove = newPos - origin;
                    totalMove.y = 0;
                    Vector3 moveDir = totalMove.normalized;

                    move_data.id     = mOwner.UID.obj_idx;
                    move_data.pos.px = (int)(origin.x * 100.0f);
                    move_data.pos.py = (int)(origin.z * 100.0f);
                    move_data.dir    = Maths.Util.VectorToAngle(moveDir);

                    float   totalMoveLen = totalMove.magnitude;
                    Vector3 xz_offset    = offset;
                    xz_offset.y = 0;
                    float ortMoveLen = xz_offset.magnitude;
                    if (totalMoveLen > 0 && ortMoveLen > 0)
                    {
                        move_data.speed = (uint)(mOwner.MoveSpeed * (totalMoveLen / ortMoveLen) * 100);
                    }
                    else
                    {
                        move_data.speed = 0;
                    }

                    mSliderData.Assign(move_data);
                    slider_data.slide = move_data;
                    NetClient.GetCrossClient().SendData <C2SNwarSlide>(NetMsg.MSG_NWAR_SLIDE, slider_data);
                }
            }

            mOwnerTrans.position = newPos;
            OnMove();
        }
Exemple #4
0
        /// <summary>
        /// 计算到目标点的路径
        /// </summary>
        void CalcMovePath()
        {
            if (mWalkMode == EWalkMode.EWM_Dst)// 只有走到目标点的行走方式才需要寻路
            {
                mDestList.Clear();
                walkMeshPath.ClearCorners();
                XNavMesh.CalculatePath(mOwnerTrans.position, mDst, LevelManager.GetInstance().AreaExclude, walkMeshPath);
                if (walkMeshPath.status == XNavMeshPathStatus.PathComplete && walkMeshPath.corners.GetLength(0) >= 2)
                {
                    // 调整路径的拐弯点
                    Vector3[] adjuestCorners = walkMeshPath.corners;

#if UNITY_EDITOR
                    if (mOwner is LocalPlayer)
                    {
                        for (int j = 1; j < adjuestCorners.Length; ++j)
                        {
                            Debug.DrawLine(adjuestCorners[j - 1], adjuestCorners[j], Color.red, 1.0f * adjuestCorners.Length);
                        }
                    }
#endif

                    int len = adjuestCorners.Length;
                    if (len > 3)
                    {
                        adjuestCorners    = new Vector3[len];
                        adjuestCorners[0] = walkMeshPath.corners[0];
                        for (int i = 1; i < len; ++i)
                        {
                            if (i + 1 >= len)
                            {
                                adjuestCorners[i] = walkMeshPath.corners[i];
                                break;
                            }

                            Vector3 pre_vec = walkMeshPath.corners[i - 1] - walkMeshPath.corners[i];
                            pre_vec.y = 0;
                            pre_vec.Normalize();
                            Vector3 next_vec = walkMeshPath.corners[i + 1] - walkMeshPath.corners[i];
                            next_vec.y = 0;
                            next_vec.Normalize();
                            if (pre_vec.sqrMagnitude < minCornerDis || next_vec.sqrMagnitude < minCornerDis)
                            {
                                adjuestCorners[i] = walkMeshPath.corners[i];
                                continue;
                            }

                            // 先计算调整后的位置(增加MoveImpl.Radius)
                            Vector3 middle_vec    = pre_vec + next_vec;
                            var     adjuestCorner = walkMeshPath.corners[i] - middle_vec * (0.8f + MoveImpl.Radius * 2);

                            // 在该位置点附近进行采样
                            XNavMeshHit nearestHit;
                            if (XNavMesh.SamplePosition(adjuestCorner, out nearestHit, 5f, LevelManager.GetInstance().AreaExclude))
                            {
                                // 如果调整后的位置可行走,则使用新位置,否则使用原始位置
                                var dis = nearestHit.position - adjuestCorner;
                                if (dis.sqrMagnitude < 0.01f)
                                {
                                    adjuestCorners[i] = walkMeshPath.corners[i] - middle_vec * 0.8f;
                                }
                                else
                                {
                                    adjuestCorners[i] = walkMeshPath.corners[i];
                                }
                            }
                            else
                            {
                                adjuestCorners[i] = walkMeshPath.corners[i];
                            }
                        }
                    }

                    mDst = adjuestCorners[1];
                    for (int j = 1; j < adjuestCorners.Length; ++j)
                    {
                        mDestList.Add(adjuestCorners[j]);
                    }

                    if (mOwner.IsLocalPlayer)
                    {
                        ClientEventMgr.GetInstance().FireEvent((int)ClientEvent.CE_ACTOR_PATH_POINTS_CHANGED, null);
                    }

#if UNITY_EDITOR
                    if (mOwner is LocalPlayer)
                    {
                        for (int j = 1; j < adjuestCorners.Length; ++j)
                        {
                            Debug.DrawLine(adjuestCorners[j - 1], adjuestCorners[j], Color.green, 1f * adjuestCorners.Length);
                        }
                    }
#endif
                }
                else
                {
                    // 如果寻路不成功,则设置目标点为初始点
                    mDst = mOwnerTrans.position;
                }
                mWalkToPoint = false;
            }
        }
        /// <summary>
        /// 开始
        /// </summary>
        public override bool Begin(SkillAction action)
        {
            base.Begin(action);

            m_DynamicStageTime = mSkillAction.ActionData.CastingStageTime;
            m_RealTargetPos    = Vector3.zero;

            // 判定是否要进入持续施法阶段
            if (mSkillAction.ActionData.SkillInfo.CastingTime <= 0.0f)
            {
                return(false);
            }

            Actor src_actor = mSkillAction.SkillParent.SrcActor;

            // 技能的隐身
            if (mSkillAction.ActionData.SkillInfo.Invisible)
            {
                if (src_actor.mVisibleCtrl.VisibleMode == EVisibleMode.Visible)
                {
                    mSkillAction.HideActor = true;
                    src_actor.mVisibleCtrl.SetActorVisible(false, true, false, VisiblePriority.SKILL);
                }
            }

            // 播放动画
            string casting_ani = mSkillAction.ActionData.CastingAnimation;

            if (casting_ani != string.Empty && casting_ani != mSkillAction.ActionData.SkillAnimation)
            {
                src_actor.Play(mSkillAction.ActionData.CastingAnimation);
            }
            src_actor.SetAnimationSpeed(mSkillAction.SkillParent.SpeedScale);

            // 施法阶段的位移
            MoveCtrl move_ctrl = src_actor.MoveCtrl;

            mSkillAction.SkillParent.MovingSpeed = mSkillAction.ActionData.SkillInfo.CastingSpeed;
            src_actor.MoveSpeed = mSkillAction.ActionData.SkillInfo.CastingSpeed;
            mSkillAction.BeginMove();

            uint target_id = mSkillAction.SkillParent.TargetID;     // 目标玩家的id

            if (target_id == 0)                                     // 无目标玩家
            {
                move_ctrl.MoveDirInAttacking(src_actor.ForwardDir); // 沿当前方向移动
                Vector3 src_pos = src_actor.Trans.position;
                m_RealTargetPos = src_pos + mSkillAction.SkillParent.AttackDir * mSkillAction.ActionData.SkillInfo.CastingSpeed * mSkillAction.ActionData.CastingStageTime;
                XNavMeshHit hit;
                if (XNavMesh.Raycast(src_pos, m_RealTargetPos, out hit, xc.Dungeon.LevelManager.GetInstance().AreaExclude))
                {
                    m_RealTargetPos = PhysicsHelp.BoundaryHitPos(src_pos, hit.position);
                }
            }
            else// 有目标玩家
            {
                Vector3 src_pos      = src_actor.Trans.position;
                Actor   target_actor = ActorManager.Instance.GetPlayer(target_id);// 获取目标玩家

                Vector3 target_pos = Vector3.zero;
                if (target_actor != null)
                {
                    target_pos = target_actor.Trans.position;
                    Vector3 vec = target_pos - src_pos;
                    float   len = vec.magnitude;

                    if (len > mSkillAction.RushTargetRange)
                    {
                        float real_len = len - mSkillAction.RushTargetRange;
                        target_pos = src_pos + vec * real_len / len;
                        XNavMeshHit hit;
                        if (XNavMesh.Raycast(src_pos, target_pos, out hit, xc.Dungeon.LevelManager.GetInstance().AreaExclude))
                        {
                            target_pos = PhysicsHelp.BoundaryHitPos(src_pos, hit.position);
                        }

                        if (mSkillAction.ActionData.SkillInfo.CastingSpeed != 0)
                        {
                            m_RealTargetPos = target_pos;
                            float calc_castingTime = real_len / mSkillAction.ActionData.SkillInfo.CastingSpeed;// 根据距离和速度计算施法阶段的时间
                            float fix_castingTime  = mSkillAction.ActionData.CastingStageTime;
                            if (calc_castingTime < fix_castingTime)
                            {
                                m_DynamicStageTime = calc_castingTime;
                            }
                        }
                    }
                    else
                    {
                        target_pos         = src_pos;
                        m_DynamicStageTime = 0;
                    }

                    move_ctrl.MoveDirInAttacking(vec);// 冲到目标点的方向
                }
                else
                {
                    target_pos = src_pos + mSkillAction.SkillParent.AttackDir * mSkillAction.ActionData.SkillInfo.CastingSpeed * mSkillAction.ActionData.CastingStageTime;
                    XNavMeshHit hit;
                    if (XNavMesh.Raycast(src_pos, target_pos, out hit, xc.Dungeon.LevelManager.GetInstance().AreaExclude))
                    {
                        target_pos      = PhysicsHelp.BoundaryHitPos(src_pos, hit.position);
                        m_RealTargetPos = target_pos;
                    }
                }

                if (src_actor.AttackCtrl.mIsSendMsg)
                {
                    C2SNwarChargeStop charge_stop = new C2SNwarChargeStop();
                    charge_stop.skill_id = mSkillAction.ActionData.SkillInfo.Id;
                    PkgNwarMove move = new PkgNwarMove();
                    move.id = src_actor.UID.obj_idx;
                    PkgNwarPos pos = new PkgNwarPos();
                    pos.px           = (int)(target_pos.x * 100);
                    pos.py           = (int)(target_pos.z * 100);
                    move.pos         = pos;
                    move.speed       = 0;
                    move.time        = 0;
                    charge_stop.move = move;

                    NetClient.GetCrossClient().SendData <C2SNwarChargeStop>(NetMsg.MSG_NWAR_CHARGE_STOP, charge_stop);
                }
            }


            return(true);
        }