예제 #1
0
    public bool IsConnected(Vector3 startPos, Vector3 endPos)
    {
        //float ratio0 = 0;
        float ratio1 = 0;
        bool  bHit0  = false;
        bool  bHit1  = false;

        RaycastHit hitInfo;
        Vector3    dir    = endPos - startPos;
        float      length = dir.magnitude;

        dir.Normalize();
        if (length > 0.1f && CUnityUtil.RayCastWithRadius(0, startPos, dir, out hitInfo, length, CUnityUtil.LayerMaskBlockable))
        {
            //ratio0 = hitInfo.distance / length;
            bHit0 = true;
        }

        if (NavMeshManager.Instance.IsInited && !NavMeshManager.Instance.IsConnected(startPos, endPos, ref ratio1))
        {
            bHit1 = true;
        }

        return(!bHit0 && !bHit1);
    }
예제 #2
0
    //找到寻路点上第一个和目标点连通的点
    public bool FindFirstConnectedPoint(Vector3 startPos, Vector3 endPos, Vector3 polyPickExt, float stepSize, out Vector3 selectPoint)
    {
        selectPoint = endPos;

        if (IsConnected(startPos, endPos))
        {
            selectPoint = startPos;
            return(true);
        }

        if (!NavMeshManager.Instance.IsInited)
        {
            return(false);
        }

        float[] tempAllPoints = NavMeshManager.TempAllPoints;

        int     outVertNum = 0;
        Vector3 targetPos  = endPos;

        if (!NavMeshManager.Instance.GetWayPointsAtCurrentMap(startPos, targetPos, polyPickExt, stepSize, 0.1f, tempAllPoints, out outVertNum) || outVertNum <= 0)
        {
            return(false);
        }

        for (int i = 0; i < outVertNum; ++i)
        {
            var vec = new Vector3(tempAllPoints[i * 3], tempAllPoints[i * 3 + 1], tempAllPoints[i * 3 + 2]);
            vec.y = CUnityUtil.GetMapHeight(vec);

            //看是否被阻挡
            RaycastHit hitInfo;
            Vector3    dir    = endPos - startPos;
            float      length = dir.magnitude;
            if (length > 0.1f)
            {
                dir.Normalize();
                if (CUnityUtil.RayCastWithRadius(0, startPos, dir, out hitInfo, length, CUnityUtil.LayerMaskBlockable))
                {
                    break;
                }
            }

            if (NavMeshManager.Instance.IsInited && NavMeshManager.Instance.IsConnected(vec, endPos))
            {
                selectPoint = vec;
                return(true);
            }
        }

        return(false);
    }
예제 #3
0
    public bool IsCollideWithBlockable(Vector3 startPos, Vector3 endPos)
    {
        RaycastHit hitInfo;
        Vector3    dir    = endPos - startPos;
        float      length = dir.sqrMagnitude;

        if (length > 0.01f)
        {
            dir.Normalize();
            if (CUnityUtil.RayCastWithRadius(0, startPos, dir, out hitInfo, length, CUnityUtil.LayerMaskBlockable))
            {
                return(true);
            }
        }
        return(false);
    }
예제 #4
0
    //从startPos到endPos, 是否连通,包括obstacle和navmesh
    public bool IsConnected(Vector3 startPos, Vector3 endPos, out Vector3 hitPos)
    {
        hitPos = startPos;

        RaycastHit hitInfo;
        Vector3    dir    = endPos - startPos;
        float      length = dir.magnitude;

        dir.Normalize();

        float ratio0 = 0;

        if (length > 0.1f)
        {
            if (CUnityUtil.RayCastWithRadius(0, startPos, dir, out hitInfo, length, CUnityUtil.LayerMaskBlockable))
            {
                ratio0   = hitInfo.distance / length;
                hitPos   = startPos + (endPos - startPos) * ratio0;
                hitPos.y = CUnityUtil.GetMapHeight(hitPos);
                return(false);
            }
        }

        float ratio1 = 0;

        if (NavMeshManager.Instance.IsInited && !NavMeshManager.Instance.IsConnected(startPos, endPos, ref ratio1))
        {
            if (ratio1 < ratio0)
            {
                hitPos   = startPos + (endPos - startPos) * ratio1;
                hitPos.y = CUnityUtil.GetMapHeight(hitPos);
            }

            return(false);
        }

        return(true);
    }
예제 #5
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);
    }
예제 #6
0
    private bool TickHostPlayer3(float dt)
    {
        Vector3 curPos = _Owner.position;

        curPos.y += 0.6f;

        var distLeft = Util.DistanceH(curPos, _TargetPos);

        //到达检查, 如果offset为0,则停在target位置,否则停在当前位置
        if (_DestOffset > 0.0f)
        {
            if (distLeft <= _DestOffset)
            {
                _DestOffset = 0.0f;
                RealOnFinish(BEHAVIOR_RETCODE.Success, _Owner.forward);
                return(true);
            }
        }
        else if (distLeft < NEAREST_DIST)
        {
            Vector3 vPos = _TargetPos;
            vPos.y          = CUnityUtil.GetMapHeight(vPos) + _ObjectComponent.OffsetY;
            _Owner.position = vPos;
            _DestOffset     = 0.0f;
            RealOnFinish(BEHAVIOR_RETCODE.Success, _Owner.forward);
            return(true);
        }

        Vector3 dir = (_TargetPos - curPos);

        dir.y    = 0;
        _MoveDir = dir.normalized;

        var nextPos = Vector3.zero;

        #region 碰撞检测
        RaycastHit hitInfo;
        //检查obstacle碰撞,中断
        if (CUnityUtil.RayCastWithRadius(0, curPos, _MoveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskMovementObstacle))
        {
            RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
            return(true);
        }

        if (CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, curPos, _MoveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskNPC))
        {
            Vector3 ahead          = _Owner.position + _Owner.forward * 1.5f;
            Vector3 avoidanceForce = ahead - hitInfo.collider.transform.position;
            avoidanceForce = avoidanceForce.normalized * MAX_AVOID_FORCE;
            Vector3 steering = (_MoveDir * _MoveSpeed + avoidanceForce).normalized;

            nextPos   = _Owner.position + _MoveSpeed * dt * steering;
            nextPos.y = CUnityUtil.GetMapHeight(nextPos) + _ObjectComponent.OffsetY;

            if (!IsValidPositionStrict(nextPos))
            {
                RealOnFinish(BEHAVIOR_RETCODE.Blocked, steering);
                return(true);
            }

            steering.y = 0;
            if (!Util.IsValidDir(ref steering))
            {
                steering = _Owner.forward;
            }

            _Owner.position = nextPos;
            if (IsDirChanged)
            {
                TickAdjustDir(steering);
            }

            SyncMoveStamp(dir, false, true, _TargetPos);
            return(false);
        }
        #endregion

        #region 步长是否超过剩余距离
        //判断这次移动的距离是否超过剩余距离,停止
        float fDistMove = _MoveSpeed * dt;
        if (fDistMove >= distLeft)
        {
            Vector3 vPos = _TargetPos;
            vPos.y          = CUnityUtil.GetMapHeight(vPos) + _ObjectComponent.OffsetY;
            _Owner.position = vPos;
            RealOnFinish(BEHAVIOR_RETCODE.Success, _Owner.forward);
            return(true);
        }
        #endregion

        nextPos = curPos + _MoveSpeed * dt * _MoveDir;

        #region NextStepPos NavMesh有效性检查
        Vector3 nextValidPos = Vector3.zero;
        if (NavMeshManager.Instance.GetNearestValidPosition(nextPos, ref nextValidPos, 1.0f))
        {
            Vector3 vDelta = nextPos - nextValidPos;
            vDelta.y = 0;
            float fLen = vDelta.magnitude;
            if (fLen < 0.01f)       //navmesh寻路点
            {
                nextPos = nextValidPos;
            }
            else
            {
                float fv = Math.Min(fLen, NavMeshManager.TRACE_EXTEND_DISTANCE);        //最大可以跨出navmesh范围
                vDelta.Normalize();
                nextPos = nextValidPos + vDelta * fv;
            }

            nextPos.y = CUnityUtil.GetMapHeight(nextPos) + _ObjectComponent.OffsetY;

            Vector3 v = nextPos - curPos;
            v.y = 0;
            if (v.sqrMagnitude <= 0.0004f && _MoveSpeed * dt > 0.02f)            //停止不动且和building碰撞, block
            {
                ++_BlockOccurCount;

                if (_BlockOccurCount > 3)
                {
                    _BlockOccurCount = 0;
                    _Owner.position  = nextPos;
                    RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
                    return(true);
                }
            }
            else
            {
                _BlockOccurCount = 0;
            }
        }
        else
        {
            nextPos.y = CUnityUtil.GetMapHeight(nextPos) + _ObjectComponent.OffsetY;

            _BlockOccurCount = 0;
            RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
            return(true);
        }
        #endregion

        _Owner.position = nextPos;

        if (IsDirChanged)
        {
            TickAdjustDir(_MoveDir);
        }

        //避免频繁发送
        SyncMoveStamp(_MoveDir, false, false, _TargetPos);

        return(false);
    }
예제 #7
0
    private bool TickNavigation(float dt)
    {
        Vector3 curPos = _Owner.position;

        //offset判断, 如果offset为0,则停在target位置,否则停在当前位置
        float distSqr = Util.SquareDistanceH(curPos, _TargetPos);

        if (_DestOffset > Util.FloatZero && distSqr <= _DestOffset * _DestOffset)
        {
            _DestOffset = 0.0f;
            RealOnFinish(BEHAVIOR_RETCODE.Success, _Owner.forward);
            return(true);
        }

        if (distSqr < NEAREST_DIST * NEAREST_DIST)
        {
            Vector3 vPos = _TargetPos;
            vPos.y          = CUnityUtil.GetMapHeight(vPos) + _ObjectComponent.OffsetY;
            _Owner.position = vPos;
            _DestOffset     = 0.0f;
            RealOnFinish(BEHAVIOR_RETCODE.Success, _Owner.forward);
            return(true);
        }

        // 吸附中,需要重新计算路线
        if (_ObjectComponent.HasBehavior(BehaviorType.Adsorb))
        {
            if (!CalcHostPathFindingInfo())
            {
                _DestOffset = 0.0f;
                RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
                return(true);
            }
        }

        Vector3 vNextPos;
        var     step    = _MoveSpeed * dt;
        int     iPath   = 0;
        var     bArrive = CHostPathFindingInfo.Instance.GetNextNavPosition(step, ref curPos, ref iPath, out vNextPos);

        vNextPos.y = CUnityUtil.GetMapHeight(vNextPos) + _ObjectComponent.OffsetY;

        var facedir = vNextPos - curPos;

        facedir.y = 0;
        if (!Util.IsValidDir(ref facedir))
        {
            facedir = _Owner.forward;
        }

        //寻路到达判断
        if (bArrive)
        {
            _Owner.position = vNextPos;
            _DestOffset     = 0.0f;
            RealOnFinish(BEHAVIOR_RETCODE.Success, facedir);
            return(true);
        }
        _MoveDir = facedir;

        curPos.y += 0.6f;
        RaycastHit hitInfo;

        #region Obstacle碰撞检测
        //检查obstacle碰撞,中断
        if (CUnityUtil.RayCastWithRadius(0, curPos, _MoveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskMovementObstacle))
        {
            _DestOffset = 0.0f;
            RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
            return(true);
        }
        #endregion

        if (IgnoreCollisionDetect)           //忽略碰撞
        {
            _Owner.position = vNextPos;

            if (IsDirChanged)
            {
                TickAdjustDir(_MoveDir);
            }

            SyncMoveStamp(_MoveDir, false, false, vNextPos);
            return(false);
        }
        else
        {
            bool bLastCollide = _IsCollidedWithObjects;

            #region NPC碰撞检测
            _IsCollidedWithObjects = CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, curPos, _MoveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskNPC);

            if (_IsCollidedWithObjects)
            {
                float dist = Util.SquareDistanceH(curPos, _NavCalcStartPosition);
                if (dist < 1.0f)
                {
                    ++_CollideTryCount;
                }
                else
                {
                    _CollideTryCount = 0;
                }

                if (_CollideTryCount >= 1)
                {
                    _IsCollidedWithObjects = false;
                    _CollideTryCount       = 0;
                }
            }
            #endregion

            if (_IsCollidedWithObjects)
            {
                Vector3 ahead = _Owner.position + _Owner.forward * 1.5f;
                ahead.y = 0;
                Vector3 avoidanceForce = ahead - hitInfo.collider.transform.position;
                avoidanceForce.y = 0;
                avoidanceForce   = avoidanceForce.normalized * MAX_AVOID_FORCE;
                Vector3 steering = (_MoveDir * _MoveSpeed + avoidanceForce).normalized;

                vNextPos = _Owner.position + _MoveSpeed * Math.Max(0.03f, dt) * steering;
                if (!IsValidPositionStrict(vNextPos))                  //尝试不成功则恢复,否则会卡住
                {
                    vNextPos = _Owner.position;
                }
                else
                {
                    vNextPos.y = CUnityUtil.GetMapHeight(vNextPos) + _ObjectComponent.OffsetY;
                }

                _Owner.position = vNextPos;
                if (IsDirChanged)
                {
                    TickAdjustDir(steering);
                }

                SyncMoveStamp(steering, false, true, _TargetPos);
                return(false);
            }
            else
            {
                if (bLastCollide)                   //由碰撞变为不碰撞
                {
                    if (!CalcHostPathFindingInfo()) //以当前点继续寻路
                    {
                        _DestOffset = 0.0f;
                        RealOnFinish(BEHAVIOR_RETCODE.Blocked, _MoveDir);
                        return(true);
                    }

                    return(false);
                }
            }

            _Owner.position = vNextPos;
            if (IsDirChanged)
            {
                TickAdjustDir(_MoveDir);
            }

            SyncMoveStamp(_MoveDir, false, false, _TargetPos);

            return(false);
        }
    }
예제 #8
0
    bool TickHostPlayer3(float dt)
    {
        if (_TargetTrans == null)
        {
            RealOnFinish(BEHAVIOR_RETCODE.Failed, _Owner.forward);
            return(true);
        }

        Vector3 curPos      = _Owner.position;
        Vector3 targetPos   = _TargetTrans.position;
        float   distanceSqr = Util.SquareDistanceH(curPos, targetPos);

        Vector3 dir = (targetPos - curPos);

        dir.y = 0;
        Vector3 moveDir = dir.normalized;

        if (distanceSqr < _MaxDistanceSqr && distanceSqr > _MinDistanceSqr)
        {
            if (!_IsLoop)
            {
                RealOnFinish(BEHAVIOR_RETCODE.Success, moveDir);
                return(true);
            }
            else
            {
                return(false);
            }
        }

        curPos.y += 0.6f;
        RaycastHit hitInfo;
        Vector3    nextPos;

        //检查obstacle碰撞,中断
        if (CUnityUtil.RayCastWithRadius(0, curPos, moveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskMovementObstacle))
        {
            RealOnFinish(BEHAVIOR_RETCODE.Blocked, moveDir);
            return(true);
        }

        if (CUnityUtil.RayCastWithRadius(Main.HostPlayerRadius, curPos, moveDir, out hitInfo, CUnityUtil.TraceForwardDistance, CUnityUtil.LayerMaskNPC))
        {
            Vector3 ahead          = _Owner.position + _Owner.forward * 1.5f;
            Vector3 avoidanceForce = ahead - hitInfo.collider.transform.position;
            avoidanceForce = avoidanceForce.normalized * MAX_AVOID_FORCE;
            Vector3 steering = (moveDir * _MoveSpeed + avoidanceForce).normalized;

            nextPos = _Owner.position + _MoveSpeed * dt * steering;
            if (!IsValidPositionStrict(nextPos))
            {
                RealOnFinish(BEHAVIOR_RETCODE.Blocked, steering);
                return(true);
            }

            dir   = steering;
            dir.y = 0;
            Vector3 vNormalDir;
            if (!Util.IsValidDir(ref dir))
            {
                dir = _Owner.forward;
            }

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

            SyncMoveStamp(dir, false, true, targetPos);
            return(false);
        }

        //判断这次移动的距离是否超过剩余距离,停止
        float fDistMove = _MoveSpeed * dt;

        if (fDistMove * fDistMove >= distanceSqr)
        {
            targetPos.y     = CUnityUtil.GetMapHeight(targetPos) + _ObjectComponent.OffsetY;
            _Owner.position = targetPos;
            var facedir = targetPos - curPos;
            facedir.y = 0;
            if (!Util.IsValidDir(ref facedir))
            {
                facedir = _Owner.forward;
            }

            RealOnFinish(BEHAVIOR_RETCODE.Success, facedir);
            return(true);
        }

        nextPos   = curPos + _MoveSpeed * dt * moveDir;
        nextPos.y = CUnityUtil.GetMapHeight(nextPos) + _ObjectComponent.OffsetY;
        Vector3 nearestPos = new Vector3();

        if (NavMeshManager.Instance.GetNearestValidPosition(nextPos, ref nearestPos, 1.0f))
        {
            Vector3 vDelta = nextPos - nearestPos;
            vDelta.y = 0;
            float fLen = vDelta.magnitude;
            if (fLen < 0.01f)       //navmesh寻路点
            {
                nextPos = nearestPos;
            }
            else
            {
                float fv = Math.Min(fLen, NavMeshManager.TRACE_EXTEND_DISTANCE);        //最大可以跨出navmesh范围
                vDelta.Normalize();
                nextPos = nearestPos + vDelta * fv;
            }

            Vector3 v = nextPos - curPos;
            v.y = 0;
            if (v.sqrMagnitude <= 0.0004f && _MoveSpeed * dt > 0.02f)            //停止不动且和building碰撞, block
            {
                ++_BlockCount;

                if (_BlockCount > 3)
                {
                    _BlockCount = 0;
                    RealOnFinish(BEHAVIOR_RETCODE.Blocked, moveDir);
                    return(true);
                }
            }
            else
            {
                _BlockCount = 0;
            }
        }
        else
        {
            _BlockCount = 0;
            RealOnFinish(BEHAVIOR_RETCODE.Blocked, moveDir);
            return(true);
        }

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

        TickAdjustDir(moveDir);

        SyncMoveStamp(moveDir, false, false, targetPos);
        return(false);
    }
예제 #9
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);
    }