public void SetData(Vector3 targetPos, float speed, LuaFunction cb, int objID, float fOffset, bool autopathing) { if (_ObjectComponent == null) { _ObjectComponent = _Owner.GetComponent <ObjectBehaviour>(); } _TargetPos = targetPos; #region 主角自动寻路判断逻辑 if (_OwnerType == ObjectBehaviour.OBJ_TYPE.HOSTPLAYER) { if (fOffset > 0.0f && Util.DistanceH(_Owner.transform.position, targetPos) < fOffset) //检查是否距离过近, 取消寻路,走直线逻辑 { CHostPathFindingInfo.Instance.Clear(); } else { CalcHostPathFindingInfo(); SetCameraQuickFollow(autopathing); } } #endregion _MoveSpeed = speed; _TargetPos.y = CUnityUtil.GetMapHeight(_TargetPos) + _ObjectComponent.OffsetY; // 只需要在设置目标点时,计算一次高度 _DestOffset = fOffset; if (OnFinishCallbackRef != null) { OnFinishCallbackRef.Release(); } OnFinishCallbackRef = cb; _BlockOccurCount = 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); }
public void HandleClick(Vector2 scr_pos, bool can_touch_ground) { Camera main_camera = Main.Main3DCamera; if (main_camera != null) { Vector3 scr_pos3 = new Vector3(scr_pos.x, scr_pos.y); RaycastHit hit_info; Ray ray = main_camera.ScreenPointToRay(scr_pos3); int ray_mask; if (can_touch_ground) { ray_mask = CUnityUtil.LayerMaskEntity | CUnityUtil.LayerMaskClickable | CUnityUtil.LayerMaskTerrainBuilding; } else { ray_mask = CUnityUtil.LayerMaskHostPlayer; } if (Physics.Raycast(ray, out hit_info, Mathf.Infinity, ray_mask)) { Collider cd = hit_info.collider; if (cd == null) { return; } if (cd.gameObject.layer == CUnityUtil.Layer_Terrain) { Vector3 pos = hit_info.point; LuaScriptMgr.Instance.CallLuaOnClickGroundFunc(pos); } else if (cd.gameObject.layer == CUnityUtil.Layer_Building) { Vector3 pos = hit_info.point; pos.y = CUnityUtil.GetMapHeight(pos); LuaScriptMgr.Instance.CallLuaOnClickGroundFunc(pos); } else if (cd.gameObject.layer != CUnityUtil.Layer_Unblockable) { ObjectBehaviour oc = cd.gameObject.GetComponentInParent <ObjectBehaviour>(); if (oc != null) { oc.OnClick(); } } } } }
public bool TickOtherEntity(float dt) { Vector3 pos = _Owner.position; //计算方向,移动 _MoveDir = _TargetPos - pos; _MoveDir.y = 0; float fDistLeft = 0; if (!Util.IsValidDir(ref _MoveDir, ref fDistLeft)) { _MoveDir = _Owner.forward; } float fDeltaMove = _MoveSpeed * dt; float fMinDist = Mathf.Max(fDeltaMove, NEAREST_DIST); //判断这次移动的距离是否超过剩余距离,停止 if (fDistLeft <= fMinDist) { Vector3 vPos = _TargetPos; //到达 vPos.y = CUnityUtil.GetMapHeight(vPos) + _ObjectComponent.OffsetY; _Owner.position = vPos; //到达 RealOnFinish(BEHAVIOR_RETCODE.Success, _MoveDir); return(true); } pos = _Owner.position + fDeltaMove * _MoveDir; if (Util.IsNaN(pos)) { return(false); } pos.y = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY; _Owner.position = pos; if (!_ObjectComponent.HasTurnBehavior()) //如果同时有转向,则不设置方向 { if (IsDirChanged) { TickAdjustDir(_MoveDir); } } return(false); }
public bool TickOtherEntity(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 desired = targetPos - _Owner.position; desired.y = 0; if (!Util.IsValidDir(ref desired)) { desired = _Owner.forward; } if (distanceSqr < _MaxDistanceSqr && distanceSqr > _MinDistanceSqr) { if (!_IsLoop) { RealOnFinish(BEHAVIOR_RETCODE.Success, desired); return(true); } else { return(false); } } Vector3 pos = _Owner.position + _MoveSpeed * dt * desired; if (!_ObjectComponent.HasTurnBehavior()) //如果同时有转向,则不设置方向 { TickAdjustDir(desired); // desired } pos.y = CUnityUtil.GetMapHeight(pos) + _ObjectComponent.OffsetY; _Owner.position = pos; return(false); }
private static int GetMapHeight(IntPtr L) { int count = LuaDLL.lua_gettop(L); const int nRet = 1; if ((count == 1 && LuaScriptMgr.CheckTypes(L, 1, typeof(LuaTable)))) { Vector3 pos = LuaScriptMgr.GetVector3(L, 1); float heigth = CUnityUtil.GetMapHeight(pos); LuaScriptMgr.Push(L, heigth); } else { LogParamError("GetMapHeight", count); LuaScriptMgr.Push(L, 0); } return(CheckReturnNum(L, count, nRet)); }
public override bool Tick(float dt) { if (_ObjectComponent == null) { _ObjectComponent = _Owner.GetComponent <ObjectBehaviour>(); } // 其他玩家,如果吸附中移动,以移动位置点为准;不移动时,吸附效果为准。 if (_OwnerType == ObjectBehaviour.OBJ_TYPE.ELSEPLAYER && _ObjectComponent.HasBehavior(BehaviorType.Move)) { return(false); } var adsorbDir = _AdsorbInfo.Position - _Owner.position; adsorbDir.y = 0; adsorbDir = adsorbDir.normalized; var moveStep = adsorbDir * _AdsorbInfo.Speed * dt; Vector3 newPos; if (Util.DistanceH(_AdsorbInfo.Position, _Owner.position) < Util.MagnitudeH(moveStep)) { newPos = _AdsorbInfo.Position; } else { newPos = _Owner.position + moveStep; } newPos.y = CUnityUtil.GetMapHeight(newPos) + _ObjectComponent.OffsetY; if (IsValidPositionStrict(newPos) && Util.DistanceH(newPos, _Owner.position) > Util.FloatZero) { //Debug.LogWarningFormat("{0} {1} Adsorb", Time.frameCount, _Owner.position); //Debug.LogWarningFormat("{0} {1} Adsorb", Time.frameCount, newPos); _Owner.position = newPos; } return(false); }
//从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); }
public bool ShowFileMapRegion(string filename) { if (_lastFileMapRegionName != filename) { FileMapRegion newFile = new FileMapRegion(); try { byte[] region_data = Util.ReadFile(filename); if (!newFile.ReadFromMemory(region_data)) { HobaDebuger.LogWarning("ShowFileMapRegion, Failed to load " + filename); return(false); } } catch (Exception) { HobaDebuger.LogWarning("ShowFileMapRegion, Failed to load " + filename); return(false); } _fileMapRegion = newFile; _lastFileMapRegionName = filename; } for (int i = 0; i < _mapRegionGameObjList.Count; ++i) { GameObject go = _mapRegionGameObjList[i]; if (go != null) { GameObject.Destroy(go); } } _mapRegionGameObjList.Clear(); List <int> Keys = new List <int>(_fileMapRegion.RegionMap.Keys); for (int i = 0; i < Keys.Count; ++i) { FileRegion fileRegion = _fileMapRegion.RegionMap[Keys[i]]; // HashSet <uint> regionGridSet = fileRegion.RegionGridSet; List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); Vector3[] vGrid = new Vector3[4]; int voffset = 0; foreach (uint v in regionGridSet) { if (vertices.Count + 4 > 60000) //split { int index = _mapRegionGameObjList.Count; GameObject go = new GameObject(HobaText.Format("MapRegionGameObj_{0}_{1}", Keys[i], index)); MeshRenderer meshRenderer = go.AddComponent <MeshRenderer>(); meshRenderer.enabled = true; meshRenderer.name = HobaText.Format("MapRegionGameObj_{0}_{1}", Keys[i], index); meshRenderer.material.shader = Shader.Find("Legacy Shaders/Bumped Diffuse"); meshRenderer.material.color = GetMeshColor(Keys[i]); CUnityUtil.DisableLightAndShadow(meshRenderer); MeshFilter meshFilter = go.AddComponent <MeshFilter>(); meshFilter.sharedMesh = new Mesh(); meshFilter.sharedMesh.name = HobaText.Format("MeshFilterMesh_{0}_{1}", Keys[i], index); meshFilter.sharedMesh.vertices = vertices.ToArray(); meshFilter.sharedMesh.triangles = triangles.ToArray(); _mapRegionGameObjList.Add(go); vertices.Clear(); triangles.Clear(); voffset = 0; } uint row = (v & 0xffff0000) >> 16; uint col = (v & 0xffff); _fileMapRegion.GetGridPositions(row, col, vGrid, 0); float fH0 = CUnityUtil.GetMapHeight(vGrid[0]); float fH1 = CUnityUtil.GetMapHeight(vGrid[1]); float fH2 = CUnityUtil.GetMapHeight(vGrid[2]); float fH3 = CUnityUtil.GetMapHeight(vGrid[3]); // if (fH0 == 0.0f || fH1 == 0.0f || fH2 == 0.0f || fH3 == 0.0f) // continue; vGrid[0].y = fH0 + 0.1f; vGrid[1].y = fH1 + 0.1f; vGrid[2].y = fH2 + 0.1f; vGrid[3].y = fH3 + 0.1f; vertices.Add(vGrid[0]); vertices.Add(vGrid[1]); vertices.Add(vGrid[2]); vertices.Add(vGrid[3]); triangles.Add(voffset + 0); triangles.Add(voffset + 1); triangles.Add(voffset + 2); triangles.Add(voffset + 3); triangles.Add(voffset + 2); triangles.Add(voffset + 1); voffset += 4; } if (vertices.Count > 0) { int index = _mapRegionGameObjList.Count; GameObject go = new GameObject(HobaText.Format("MapRegionGameObj_{0}_{1}", Keys[i], index)); MeshRenderer meshRenderer = go.AddComponent <MeshRenderer>(); meshRenderer.enabled = true; meshRenderer.name = HobaText.Format("MapRegionGameObj_{0}_{1}", Keys[i], index); meshRenderer.material.shader = Shader.Find("Legacy Shaders/Bumped Diffuse"); meshRenderer.material.color = GetMeshColor(Keys[i]); CUnityUtil.DisableLightAndShadow(meshRenderer); MeshFilter meshFilter = go.AddComponent <MeshFilter>(); meshFilter.sharedMesh = new Mesh(); meshFilter.sharedMesh.name = HobaText.Format("MeshFilterMesh_{0}_{1}", Keys[i], index); meshFilter.sharedMesh.vertices = vertices.ToArray(); meshFilter.sharedMesh.triangles = triangles.ToArray(); _mapRegionGameObjList.Add(go); vertices.Clear(); triangles.Clear(); voffset = 0; } } return(true); }
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); }
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); }
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); } }
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); }
/* * target:目标 * hud: 发出点 * ro_ori: 初始角度 * ro_end:结束角度 * bullet:发射子物体 */ public void BallCurvFly(Vector3 target, GameObject fromObj, GameObject bulletObj, float angle) { if (fromObj == null || bulletObj == null) { return; } Transform from = fromObj.transform; Transform bullet = bulletObj.transform; Vector3 fromPos = from.position; var length = Util.DistanceH(target, fromPos); var cost = length / _DevSpeed;; var costHSplit = 0.5f; var height = 0f; //大于1米的时候 分割抛物线 if ((target.y - fromPos.y) > 1f) { height = length / DEV_LENGTH * _DevHeight / 2 + (target.y - fromPos.y); costHSplit = 1 - (height - (target.y - fromPos.y)) / height; } else { height = length / DEV_LENGTH * _DevHeight; } bullet.position = from.position; var oriy = bullet.position.y; var destPos = target; destPos.y = CUnityUtil.GetMapHeight(destPos); if (destPos.y <= CUnityUtil.InvalidHeight) { destPos.y = oriy; } // var midPos = from.position + (destPos - from.position) / 2; // midPos.y = oriy + height; //水平 _TwList.Add(bullet.DOMoveX(destPos.x, cost).SetEase(Ease.Linear)); _TwList.Add(bullet.DOMoveZ(destPos.z, cost).SetEase(Ease.Linear)); //高度 var tw = bullet.DOMoveY(oriy + height, cost * costHSplit); tw.SetEase(Ease.OutQuad); _TwList.Add(tw); var twLook = bullet.DORotateQuaternion(bullet.rotation * Quaternion.Euler(angle, 0, 0), cost * costHSplit); _TwList.Add(twLook); twLook.OnComplete(() => { _TwList.Add(bullet.DOLookAt(destPos, cost * (1 - costHSplit))); }); tw.OnComplete(() => { var tw2 = bullet.DOMoveY(destPos.y, cost * (1 - costHSplit)); tw2.SetEase(Ease.InQuad); _TwList.Add(tw2); _IsArrived = true; }); }
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); }