예제 #1
0
    public override bool Tick(float dt)
    {
        Joystick joystick = Joystick.Instance;

        if (joystick == null)
        {
            return(true);
        }

        _MoveDir = joystick.MoveDir;

        bool bValidDir = Util.IsValidDir(ref _MoveDir);

        if (!bValidDir)
        {
            return(false);
        }

        TickAdjustDir(_MoveDir);

        var curDir = _Owner.forward;

        Vector3 pos = _Owner.position;

        pos.y += 0.6f;


        #region 碰撞检测
        RaycastHit hitInfo;
        if (CUnityUtil.RayCastWithRadius(0, pos, curDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskMovementObstacle))
        {
            SyncMoveStampWhenNoProgress();
            return(false);
        }

        if (CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, pos, curDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskNPC))
        {
            // 修正运动方向
            Vector3 adjustDir;
            {
                Vector3 hitNormal = hitInfo.normal;
                var     v         = Vector3.Cross(hitNormal, curDir);
                adjustDir   = Vector3.Cross(v, hitNormal);
                adjustDir.y = 0;
                adjustDir.Normalize();
            }

            //TickAdjustDir(adjustDir);
            //	朝调整方向trace,如果还有boxcollider则不再寻找新的方向
            if (CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, pos, adjustDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskNPC))
            {
                SyncMoveStampWhenNoProgress();
                return(false);
            }

            pos = _Owner.position + _MoveSpeed * dt * adjustDir;
            if (!IsValidPositionStrict(pos))
            {
                SyncMoveStampWhenNoProgress();
                return(false);
            }

            pos.y           = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY;
            _Owner.position = pos;
            SyncMoveStampWhenProgress();

            return(false);
        }
        #endregion


        float fTestDist = NavMeshManager.TRACE_EXTEND_DISTANCE;
        if (_MoveSpeed * dt > fTestDist)                //需要测试一个比较近的距离
        {
            Vector3 vTemp = _Owner.position + fTestDist * curDir;
            if (!NavMeshManager.Instance.IsValidPositionStrict(vTemp, false, 0.3f))
            {
                SyncMoveStampWhenNoProgress();
                return(false);
            }
        }

        {
            Vector3 vNearest = pos;
            pos   = _Owner.position + _MoveSpeed * dt * curDir;
            pos.y = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY;
            if (NavMeshManager.Instance.GetNearestValidPosition(pos, ref vNearest))
            {
                //取目标点和最近navmesh点的插值,这样可以沿移动方向在navmesh周边滑动
                Vector3 vDelta = pos - vNearest;
                vDelta.y = 0;
                float fLen = vDelta.magnitude;
                if (fLen < 0.01f)
                {
                    pos = vNearest;
                }
                else
                {
                    float fv = Math.Min(fLen, NavMeshManager.TRACE_EXTEND_DISTANCE);                //最大超出navmesh边界0.2 但也不能被服务器拉回 NavMeshManager.IsValidPosition
                    vDelta.Normalize();
                    pos = vNearest + vDelta * fv;
                }
            }
            else
            {
                SyncMoveStampWhenNoProgress();
                return(false);
            }
        }

        if (NavMeshManager.Instance.IsValidPositionStrict(pos, false, NavMeshManager.TRACE_EXTEND_DISTANCE))           //摇杆必须为navmesh有效点,否则会被服务器拉回
        {
            pos.y = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY;
            if (!CUnityUtil.IsHeightAccept(pos, _Owner.position))     //高度不合法
            {
                SyncMoveStampWhenNoProgress();
                return(false);
            }

            _Owner.position = pos;
            SyncMoveStampWhenProgress();
        }
        else
        {
            SyncMoveStampWhenNoProgress();
        }

        return(false);
    }
예제 #2
0
    public override bool Tick(float dt)
    {
        if (_FinishedTime <= Time.time)
        {
            //Debug.LogFormat("Dash End {0} @{1}", _Owner.position, Time.time);
            RealOnFinish(BEHAVIOR_RETCODE.Success, _Direction);
            return(true);
        }

        // 如果是主角,客户端计算,通知服务器;非主角,完全听服务器的
        if (_OwnerType == ObjectBehaviour.OBJ_TYPE.HOSTPLAYER)
        {
            #region 摇杆控制方向
            if (_CanChangeDir)
            {
                Joystick joystick = Joystick.Instance;
                if (joystick != null && !joystick.MoveDir.IsZero())
                {
                    var destDir  = joystick.MoveDir;
                    var resetDir = _LerpDestDir.IsZero();
                    if (!resetDir)
                    {
                        var angle0 = Vector3.Angle(_LerpDestDir, destDir);
                        if (Vector3.Dot(Vector3.up, Vector3.Cross(_LerpDestDir, destDir)) < 0)
                        {
                            angle0 = 180 - angle0;
                        }

                        resetDir = angle0 > 10;
                    }

                    if (resetDir)
                    {
                        _LerpDestDir = destDir;
                    }
                }

                var newDir = Vector3.Slerp(_Direction, _LerpDestDir, RotationLerpFactor);
                _Direction     = newDir.normalized;
                _Owner.forward = _Direction;

                if (_BlockedEnemyId == 0 && (Time.time - LastSyncTimestamp > 0.1f))
                {
                    var maxDis = _Speed * (_FinishedTime - Time.time);
                    var dis    = Util.GetMaxValidDistance(_Owner.position, _Direction, maxDis);
                    _Destination = _Owner.position + _Direction * dis;
                    // 需要重新同步
                    _ObjectComponent.SyncHostDashInfo(_Owner.position, _Direction, _Destination);
                    LastSyncTimestamp = Time.time;
                }
            }
            #endregion

            Vector3 castpos = _Owner.position;
            castpos.y += 0.6f;      //拔高0.6米进行前方向trace
            RaycastHit hitInfo;

            var raycastStep = _Speed * dt;
            if (raycastStep < 1)
            {
                raycastStep = 1;
            }

            #region 检查Building和obstacle碰撞
            if (CUnityUtil.RayCastWithRadius(0, castpos, _Direction, out hitInfo, raycastStep, CUnityUtil.LayerMaskMovementObstacle))
            {
                if (_CanChangeDir)
                {
                    return(false);
                }
                else
                {
                    RealOnFinish(BEHAVIOR_RETCODE.Blocked, _Direction);
                    //主角需要通知服务器停住位置
                    _ObjectComponent.SyncHostDashCollideInfo(0, false);
                    return(true);
                }
            }
            #endregion

            var collideWithEntity = CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, castpos, _Direction,
                                                                 out hitInfo, raycastStep, CUnityUtil.LayerMaskEntity);
            #region Entity碰撞
            if (collideWithEntity)
            {
                var collideObj = hitInfo.collider.gameObject.GetComponentInParent <ObjectBehaviour>();
                if (collideObj != null)
                {
                    var collideObjId = collideObj.ID32Bit;

                    if (_CanPierce)
                    {
                        // 技能移动不穿越大型怪物 范导新需求  added by zhouhenan
                        // 20190112 - 增加穿透目标前提,解决穿到怪物肚子中的问题  added by lijian
                        if (_ObjectComponent.OnCollidingHuge(collideObjId))
                        {
                            RealOnFinish(BEHAVIOR_RETCODE.Blocked, _Direction);
                            _ObjectComponent.SyncHostDashCollideInfo(0, false);
                            return(true);
                        }
                    }
                    else
                    {
                        var collideEntityType = ObjectBehaviour.CollideEntityType.All;
                        if (_OnlyCollideWithSkillTarget)
                        {
                            collideEntityType = ObjectBehaviour.CollideEntityType.OnlyTarget;
                        }
                        else if (_CanChangeDir)
                        {
                            collideEntityType = ObjectBehaviour.CollideEntityType.Enemy;
                        }

                        if (_DashContinue)
                        {
                            // 被同一只怪挡住,原地冲
                            if (_BlockedEnemyId > 0 && _BlockedEnemyId == collideObjId)
                            {
                                return(false);
                            }

                            // 确认是否被目标挡住 如果被挡,需要同步服务器
                            if (_ObjectComponent.OnCollideWithOther(collideObjId, collideEntityType))
                            {
                                _BlockedEnemyId = collideObjId;
                                _ObjectComponent.SyncHostDashCollideInfo(collideObjId, false);
                                return(false);
                            }
                            else if (_BlockedEnemyId > 0)
                            {
                                var maxDis = (_FinishedTime - Time.time) * _Speed;
                                var dis    = Util.GetMaxValidDistance(_Owner.position, _Direction, maxDis);
                                var dst    = _Owner.position + dis * _Direction;
                                _Destination = dst;
                                _ObjectComponent.SyncHostDashCollideInfo(_BlockedEnemyId, true);
                                _BlockedEnemyId = 0;
                            }
                        }
                        else
                        {
                            if (_ObjectComponent.OnCollideWithOther(collideObjId, collideEntityType))
                            {
                                _ObjectComponent.SyncHostDashCollideInfo(collideObjId, false);
                                RealOnFinish(BEHAVIOR_RETCODE.Blocked, _Direction);
                                return(true);
                            }
                        }
                    }
                }
            }
            #endregion
            else
            {
                if (_BlockedEnemyId > 0)
                {
                    var maxDis = (_FinishedTime - Time.time) * _Speed;
                    var dis    = Util.GetMaxValidDistance(_Owner.position, _Direction, maxDis);
                    var dst    = _Owner.position + dis * _Direction;
                    _Destination = dst;
                    _ObjectComponent.SyncHostDashCollideInfo(_BlockedEnemyId, true);
                    _BlockedEnemyId = 0;
                }
            }
        }
        var pos = _Owner.position + (_Speed * _Direction * dt);
        pos.y = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY;

        if (_OwnerType == ObjectBehaviour.OBJ_TYPE.HOSTPLAYER)
        {
            if (!IsValidPositionStrict(pos) || !CUnityUtil.IsHeightAccept(pos, _Owner.position))
            {
                if (_CanChangeDir)
                {
                    return(false);
                }
                else
                {
                    RealOnFinish(BEHAVIOR_RETCODE.Blocked, _Direction);
                    //主角需要通知服务器停住位置
                    _ObjectComponent.SyncHostDashCollideInfo(0, true);
                    return(true);
                }
            }
        }

        _Owner.position = pos;

        return(false);
    }