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); }
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); }