public bool IsGrounded() { Vector3 o = controller.Position + new Vector3(0, 3, 0); RaycastHit hit; if (Physics.SphereCast(o, controller.Radius, controller.Down, out hit, Mathf.Infinity, walkable)) { DebugDraw.DrawMarker(o, controller.Radius, Color.green, 0f, false); DebugDraw.DrawMarker(hit.point, controller.Radius, Color.red, 0f, false); Vector3 p = Vector3.MoveTowards(hit.point, o, controller.Radius); controller.dp = p; if (controller.Position.y <= p.y) { Ground = new GroundHit(p); return(true); } else { clearGround(); return(false); } } controller.dp = Vector3.zero; clearGround(); return(false); }
public void ProbeGround(Vector3 origin, float tolerance) { reset(); Vector3 up = controller.Up; Vector3 down = -up; Vector3 o = origin + (up * tolerance); float smallerRadius = controller.Radius - (tolerance * tolerance); RaycastHit hit; if (Physics.SphereCast(o, smallerRadius, down, out hit, Mathf.Infinity, walkable)) { var hitcolliderType = hit.collider.gameObject.GetComponent <CollisionType>(); if (hitcolliderType == null) { hitcolliderType = hit.collider.gameObject.AddComponent <CollisionType>(); } transform = hit.transform; primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); } }
private void ResetGrounds() { primaryGround = null; nearGround = null; farGround = null; flushGround = null; stepGround = null; }
/// <summary> /// 设置角色上一帧的信息 /// </summary> /// <param name="player"></param> /// <param name="time"></param> private void SetPlayerPrevInfo(PlayerEntity player, float time) { LastVelocity = Quaternion.Inverse(player.orientation.RotationYaw) * player.playerMove.Velocity.ToVector4(); CurrentVelocity = LastVelocity.ToVector4(); LastNormal = GroundInfo.surfaceNormal; DeltaTime = time; GroundInfo = player.characterContoller.Value.GetGroundHit; }
private void reset() { primaryGround = null; nearGround = null; farGround = null; stepGround = null; flushGround = null; }
// Use this for initialization void Start() { startTime = Time.time; groundHit = GetComponentInChildren <GroundHit>(); dropZone = GetComponentInChildren <DropZone>(); powerupSpawn = GetComponentInChildren <PowerupSpawn>(); craneController = GetComponentInChildren <CraneController>(); gameOverText.text = ""; }
private void ResetGrounds() { primaryGround = null; nearGround = null; farGround = null; flushGround = null; stepGround = null; doubleEdgeGrounded = false; }
void Jump() { if (!IsOnFloor()) { velocity.y -= gravity; } else { velocity.y = 0; velocity.y += jumpForce; GroundHit?.Invoke(); } }
public bool IsGrounded( bool currentlyGrounded, float distance, out Vector3 groundNormal ) { groundNormal = Vector3.zero; if( primaryGround == null || primaryGround.distance > distance ) return false; RaycastHit hit; if( Physics.SphereCast(controller.transform.position, controller.Radius, controller.Down, out hit, Mathf.Infinity, walkable) ) { Debug.Log("Found it"); primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); return true; } return false; }
public bool IsGrounded(bool currentlyGrounded, float distance, out Vector3 groundNormal) { groundNormal = Vector3.zero; if (primaryGround == null || primaryGround.distance > distance) { return(false); } RaycastHit hit; if (Physics.SphereCast(controller.transform.position, controller.Radius, controller.Down, out hit, Mathf.Infinity, walkable)) { Debug.Log("Found it"); primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); return(true); } return(false); }
public void ProbeGround( Vector3 origin, float tolerance ) { reset(); Vector3 up = controller.Up; Vector3 down = -up; Vector3 o = origin + ( up * tolerance ); float smallerRadius = controller.Radius - ( tolerance * tolerance ); RaycastHit hit; if( Physics.SphereCast( o, smallerRadius, down, out hit, Mathf.Infinity, walkable ) ) { var hitcolliderType = hit.collider.gameObject.GetComponent<CollisionType>(); if( hitcolliderType == null ) hitcolliderType = hit.collider.gameObject.AddComponent<CollisionType>(); transform = hit.transform; primaryGround = new GroundHit( hit.point, hit.normal, hit.distance ); } }
/// <summary> /// Scan the surface below us for ground. Follow up the initial scan with subsequent scans /// designed to test what kind of surface we are standing above and handle different edge cases /// </summary> /// <param name="origin">Center of the sphere for the initial SphereCast</param> /// <param name="iter">Debug tool to print out which ProbeGround iteration is being run (3 are run each frame for the controller)</param> public void ProbeGround(Vector3 origin, int iter) { ResetGrounds(); Vector3 up = controller.up; Vector3 down = -up; Vector3 o = origin + (up * Tolerance); // Reduce our radius by Tolerance squared to avoid failing the SphereCast due to clipping with walls float smallerRadius = controller.radius - (Tolerance * Tolerance); RaycastHit hit; if (Physics.SphereCast(o, smallerRadius, down, out hit, Mathf.Infinity, walkable, triggerInteraction)) { var superColType = hit.collider.gameObject.GetComponent <SuperCollisionType>(); if (superColType == null) { superColType = defaultCollisionType; } superCollisionType = superColType; transform = hit.transform; // By reducing the initial SphereCast's radius by Tolerance, our casted sphere no longer fits with // our controller's shape. Reconstruct the sphere cast with the proper radius SimulateSphereCast(hit.normal, out hit); primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); // If we are standing on a perfectly flat surface, we cannot be either on an edge, // On a slope or stepping off a ledge if (Vector3.Distance(Math3d.ProjectPointOnPlane(controller.up, controller.transform.position, hit.point), controller.transform.position) < TinyTolerance) { return; } // As we are standing on an edge, we need to retrieve the normals of the two // faces on either side of the edge and store them in nearHit and farHit Vector3 toCenter = Math3d.ProjectVectorOnPlane(up, (controller.transform.position - hit.point).normalized * TinyTolerance); Vector3 awayFromCenter = Quaternion.AngleAxis(-80.0f, Vector3.Cross(toCenter, up)) * -toCenter; Vector3 nearPoint = hit.point + toCenter + (up * TinyTolerance); Vector3 farPoint = hit.point + (awayFromCenter * 3); RaycastHit nearHit; RaycastHit farHit; Physics.Raycast(nearPoint, down, out nearHit, Mathf.Infinity, walkable, triggerInteraction); Physics.Raycast(farPoint, down, out farHit, Mathf.Infinity, walkable, triggerInteraction); nearGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); farGround = new GroundHit(farHit.point, farHit.normal, farHit.distance); // If we are currently standing on ground that should be counted as a wall, // we are likely flush against it on the ground. Retrieve what we are standing on if (Vector3.Angle(hit.normal, up) > superColType.StandAngle) { // Retrieve a vector pointing down the slope Vector3 r = Vector3.Cross(hit.normal, down); Vector3 v = Vector3.Cross(r, hit.normal); Vector3 flushOrigin = hit.point + hit.normal * TinyTolerance; RaycastHit flushHit; if (Physics.Raycast(flushOrigin, v, out flushHit, Mathf.Infinity, walkable, triggerInteraction)) { RaycastHit sphereCastHit; if (SimulateSphereCast(flushHit.normal, out sphereCastHit)) { flushGround = new GroundHit(sphereCastHit.point, sphereCastHit.normal, sphereCastHit.distance); } else { // Uh oh } } } // If we are currently standing on a ledge then the face nearest the center of the // controller should be steep enough to be counted as a wall. Retrieve the ground // it is connected to at it's base, if there exists any if (Vector3.Angle(nearHit.normal, up) > superColType.StandAngle || nearHit.distance > Tolerance) { var col = nearHit.collider.gameObject.GetComponent <SuperCollisionType>(); if (col == null) { col = defaultCollisionType; } // We contacted the wall of the ledge, rather than the landing. Raycast down // the wall to retrieve the proper landing if (Vector3.Angle(nearHit.normal, up) > col.StandAngle) { // Retrieve a vector pointing down the slope Vector3 r = Vector3.Cross(nearHit.normal, down); Vector3 v = Vector3.Cross(r, nearHit.normal); RaycastHit stepHit; if (Physics.Raycast(nearPoint, v, out stepHit, Mathf.Infinity, walkable, triggerInteraction)) { stepGround = new GroundHit(stepHit.point, stepHit.normal, stepHit.distance); } } else { stepGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); } } } // If the initial SphereCast fails, likely due to the controller clipping a wall, // fallback to a raycast simulated to SphereCast data else if (Physics.Raycast(o, down, out hit, Mathf.Infinity, walkable, triggerInteraction)) { var superColType = hit.collider.gameObject.GetComponent <SuperCollisionType>(); if (superColType == null) { superColType = defaultCollisionType; } superCollisionType = superColType; transform = hit.transform; RaycastHit sphereCastHit; if (SimulateSphereCast(hit.normal, out sphereCastHit)) { primaryGround = new GroundHit(sphereCastHit.point, sphereCastHit.normal, sphereCastHit.distance); } else { primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); } } else { Debug.LogError("[SuperCharacterComponent]: No ground was found below the player; player has escaped level"); } }
/// <summary> /// Scan the surface below us for ground. Follow up the initial scan with subsequent scans /// designed to test what kind of surface we are standing above and handle different edge cases /// </summary> /// <param name="origin">Center of the sphere for the initial SphereCast</param> /// <param name="iter">Debug tool to print out which ProbeGround iteration is being run (3 are run each frame for the controller)</param> public void ProbeGround(Vector3 origin, int iter) { ResetGrounds(); Vector3 up = controller.up; Vector3 down = -up; Vector3 o = origin + (up * Tolerance); // Reduce our radius by Tolerance squared to avoid failing the SphereCast due to clipping with walls float smallerRadius = controller.radius - (Tolerance * Tolerance); RaycastHit hit; if (Physics.SphereCast(o, smallerRadius, down, out hit, Mathf.Infinity, walkable)) { var superColType = hit.collider.gameObject.GetComponent<SuperCollisionType>(); if (superColType == null) { superColType = defaultCollisionType; } superCollisionType = superColType; transform = hit.transform; // By reducing the initial SphereCast's radius by Tolerance, our casted sphere no longer fits with // our controller's shape. Reconstruct the sphere cast with the proper radius SimulateSphereCast(hit.normal, out hit); primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); // If we are standing on a perfectly flat surface, we cannot be either on an edge, // On a slope or stepping off a ledge if (Vector3.Distance(Math3d.ProjectPointOnPlane(controller.up, controller.transform.position, hit.point), controller.transform.position) < TinyTolerance) { return; } // As we are standing on an edge, we need to retrieve the normals of the two // faces on either side of the edge and store them in nearHit and farHit Vector3 toCenter = Math3d.ProjectVectorOnPlane(up, (controller.transform.position - hit.point).normalized * TinyTolerance); Vector3 awayFromCenter = Quaternion.AngleAxis(-80.0f, Vector3.Cross(toCenter, up)) * -toCenter; Vector3 nearPoint = hit.point + toCenter + (up * TinyTolerance); Vector3 farPoint = hit.point + (awayFromCenter * 3); RaycastHit nearHit; RaycastHit farHit; Physics.Raycast(nearPoint, down, out nearHit, Mathf.Infinity, walkable); Physics.Raycast(farPoint, down, out farHit, Mathf.Infinity, walkable); nearGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); farGround = new GroundHit(farHit.point, farHit.normal, farHit.distance); // If we are currently standing on ground that should be counted as a wall, // we are likely flush against it on the ground. Retrieve what we are standing on if (Vector3.Angle(hit.normal, up) > superColType.StandAngle) { // Retrieve a vector pointing down the slope Vector3 r = Vector3.Cross(hit.normal, down); Vector3 v = Vector3.Cross(r, hit.normal); Vector3 flushOrigin = hit.point + hit.normal * TinyTolerance; RaycastHit flushHit; if (Physics.Raycast(flushOrigin, v, out flushHit, Mathf.Infinity, walkable)) { RaycastHit sphereCastHit; if (SimulateSphereCast(flushHit.normal, out sphereCastHit)) { flushGround = new GroundHit(sphereCastHit.point, sphereCastHit.normal, sphereCastHit.distance); } else { // Uh oh } } } // If we are currently standing on a ledge then the face nearest the center of the // controller should be steep enough to be counted as a wall. Retrieve the ground // it is connected to at it's base, if there exists any if (Vector3.Angle(nearHit.normal, up) > superColType.StandAngle || nearHit.distance > Tolerance) { var col = nearHit.collider.gameObject.GetComponent<SuperCollisionType>(); if (col == null) { col = defaultCollisionType; } // We contacted the wall of the ledge, rather than the landing. Raycast down // the wall to retrieve the proper landing if (Vector3.Angle(nearHit.normal, up) > col.StandAngle) { // Retrieve a vector pointing down the slope Vector3 r = Vector3.Cross(nearHit.normal, down); Vector3 v = Vector3.Cross(r, nearHit.normal); RaycastHit stepHit; if (Physics.Raycast(nearPoint, v, out stepHit, Mathf.Infinity, walkable)) { stepGround = new GroundHit(stepHit.point, stepHit.normal, stepHit.distance); } } else { stepGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); } } } // If the initial SphereCast fails, likely due to the controller clipping a wall, // fallback to a raycast simulated to SphereCast data else if (Physics.Raycast(o, down, out hit, Mathf.Infinity, walkable)) { var superColType = hit.collider.gameObject.GetComponent<SuperCollisionType>(); if (superColType == null) { superColType = defaultCollisionType; } superCollisionType = superColType; transform = hit.transform; RaycastHit sphereCastHit; if (SimulateSphereCast(hit.normal, out sphereCastHit)) { primaryGround = new GroundHit(sphereCastHit.point, sphereCastHit.normal, sphereCastHit.distance); } else { primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); } } else { Debug.LogError("[SuperCharacterComponent]: No ground was found below the player; player has escaped level"); } }
// useless for now public void OnGroundHit(GroundHit ground, GroundHit lastground, LayerMask layermask) { }
// PM_SlideMove() is one of the several variant Move() funcs available standard with the // Actor package provided. It's entire purpose is to 'slide' and 'snap' the Actor on 'stable' // surfaces whilst also dealing with the conventional issue of movement into and along blocking // planes in the physics scene. Use this method primarily if you plan on keeping your actor level // with the floor. public static void PM_SlideMove( IActorReceiver _rec, Actor _actor, ref Vector3 _pos, ref Vector3 _vel, Quaternion _orient, LayerMask _filter, float _fdt) { /* BASE CASES IN WHICH WE SHOULDN'T MOVE AT ALL */ if (_rec == null) { return; } /* STEPS: * RUN: * GROUND TRACE & GROUND SNAP -> OVERLAP -> PUSHBACK -> CONVEX HULL NORMAL (NEARBY PLANE DETECTION) -> GENERATE GEOMETRY BITMASK -> TRACING -> REPEAT */ ArchetypeHeader.Archetype _arc = _actor.GetArchetype(); SlideSnapType _snaptype = _actor.SnapType; Collider[] _colliders = _actor.Colliders; Collider _self = _arc.Collider(); Vector3[] _normals = _actor.Normals; RaycastHit[] _traces = _actor.Hits; Vector3 _tracepos = _pos; Vector3 _groundtracepos = _pos; Vector3 _lastplane = Vector3.zero; Vector3 _groundtracedir = _orient * new Vector3(0, -1, 0); Vector3 _up = _orient * new Vector3(0, 1, 0); float _tf = 1F; float _skin = ArchetypeHeader.GET_SKINEPSILON(_arc.PrimitiveType()); float _bias = ArchetypeHeader.GET_TRACEBIAS(_arc.PrimitiveType()); int _bumpcount = 0; int _groundbumpcount = 0; int _pushbackcount = 0; int _gflags = 0; GroundHit _ground = _actor.Ground; GroundHit _lastground = _actor.LastGround; _lastground.actorpoint = _ground.actorpoint; _lastground.normal = _ground.normal; _lastground.point = _ground.point; _lastground.stable = _ground.stable; _lastground.snapped = _ground.snapped; _lastground.distance = _ground.distance; _ground.Clear(); float _groundtracelen = (_lastground.stable && _lastground.snapped) ? 0.1F : 0.05F; while (_groundbumpcount++ < MAX_GROUNDBUMPS && _groundtracelen > 0F) { // trace along dir // if detected // if stable : // end trace and determine whether a snap is to occur // else : // clip along floor // continue // else : // break out of loop as no floor was detected _arc.Trace(_groundtracepos + (_up * 0.01F), _groundtracedir, _groundtracelen, _orient, _filter, 0F, QueryTriggerInteraction.Ignore, _traces, out int _groundtraces); ArchetypeHeader.TraceFilters.FindClosestFilterInvalids( ref _groundtraces, out int _i0, _bias, _self, _traces); if (_i0 >= 0) // an intersection has occured, but we aren't sure its ground yet { RaycastHit _closest = _traces[_i0]; _ground.distance = _closest.distance; _ground.normal = _closest.normal; _ground.actorpoint = _groundtracepos; _ground.stable = _actor.DetermineGroundStability(_vel, _closest, _filter); _groundtracepos += _groundtracedir * (_closest.distance); // warp regardless of stablility. We'll only be setting our trace position // to our ground trace position if a stable floor has been determined, and snapping is enabled. if (_ground.stable) { bool _cansnap = _snaptype == SlideSnapType.Always; switch (_snaptype) { case SlideSnapType.Never: _cansnap = false; break; case SlideSnapType.Toggled: _cansnap = _actor.SnapEnabled; break; } if (_cansnap) { _ground.snapped = true; } _rec.OnGroundHit(_ground, _lastground, _filter); // gonna keep the typo bc pog // shoot up check for snap availability _arc.Trace( _groundtracepos, _up, _skin + 0.1F, _orient, _filter, 0F, QueryTriggerInteraction.Ignore, _traces, out int _stepcunt); ArchetypeHeader.TraceFilters.FindClosestFilterInvalids(ref _stepcunt, out int _i1, _bias, _self, _traces); if (_i1 >= 0) { RaycastHit _snap = _traces[_i1]; Vector3 _c = Vector3.Cross(_snap.normal, _ground.normal); _c.Normalize(); Vector3 _f = Vector3.Cross(_up, _c); _f.Normalize(); if (VectorHeader.Dot(_vel, _f) <= 0F) { if (VectorHeader.Dot(_vel, _snap.normal) < 0F) { _rec.OnTraceHit(_snap, _groundtracepos, _vel); } _gflags |= (1 << 1); VectorHeader.ProjectVector(ref _vel, _c); } _groundtracepos += _up * Mathf.Max( Mathf.Min(_snap.distance - _skin, _skin), 0F); } else { _groundtracepos += _up * (_skin); } if (_ground.snapped) { _tracepos = _groundtracepos; _lastplane = _ground.normal; _gflags |= (1 << 0); VectorHeader.ClipVector(ref _vel, _ground.normal); //VectorHeader.CrossProjection(ref _vel, _up, _ground.normal); } _groundtracelen = 0F; } else { // clip, normalize, and continue: VectorHeader.ClipVector(ref _groundtracedir, _closest.normal); _groundtracedir.Normalize(); _groundtracelen -= _closest.distance; } } else // nothing discovered, end out of our ground loop. { _groundtracelen = 0F; } } while (_pushbackcount++ < ActorHeader.MAX_PUSHBACKS) { _arc.Overlap( _tracepos, _orient, _filter, 0F, QueryTriggerInteraction.Ignore, _colliders, out int _overlapsfound); ArchetypeHeader.OverlapFilters.FilterSelf( ref _overlapsfound, _self, _colliders); if (_overlapsfound == 0) // nothing ! { break; } else { for (int _colliderindex = 0; _colliderindex < _overlapsfound; _colliderindex++) { Collider _other = _colliders[_colliderindex]; Transform _otherT = _other.GetComponent <Transform>(); if (Physics.ComputePenetration(_self, _tracepos, _orient, _other, _otherT.position, _otherT.rotation, out Vector3 _normal, out float _distance)) { _tracepos += _normal * (_distance + _skin); PM_SlideDetermineImmediateGeometry(ref _vel, ref _lastplane, _actor.DeterminePlaneStability(_normal, _other), _normal, _ground.normal, _ground.stable && _ground.snapped, _up, ref _gflags); break; } } } } while (_bumpcount++ < ActorHeader.MAX_BUMPS && _tf > 0) { // Begin Trace Vector3 _trace = _vel * _fdt; float _tracelen = _trace.magnitude; // IF unable to trace any further, break and end if (_tracelen <= MIN_DISPLACEMENT) { _tf = 0; } else { _arc.Trace(_tracepos, _trace / _tracelen, _tracelen + _skin, _orient, _filter, 0F, QueryTriggerInteraction.Ignore, _traces, out int _tracecount); ArchetypeHeader.TraceFilters.FindClosestFilterInvalids( ref _tracecount, out int _i0, _bias, _self, _traces); if (_i0 <= -1) // nothing discovered ::: { _tf = 0; // end move _tracepos += _trace; break; } else // discovered an obstruction::: { RaycastHit _closest = _traces[_i0]; Vector3 _normal = _closest.normal; float _rto = _closest.distance / _tracelen; _tf -= _rto; float _dis = _closest.distance - _skin; _tracepos += (_trace / _tracelen) * _dis; // move back along the trace line! _rec.OnTraceHit(_closest, _tracepos, _vel); PM_SlideDetermineImmediateGeometry(ref _vel, ref _lastplane, _actor.DeterminePlaneStability(_normal, _closest.collider), _normal, _ground.normal, _ground.stable && _ground.snapped, _up, ref _gflags); continue; } } } _pos = _tracepos; }
/// <summary> /// /// </summary> /// <param name="origin"></param> /// <param name="iter"></param> public void ProbeGround(Vector3 origin, int iter) { //Reset _primaryGround = null; _nearGround = null; _farGround = null; _stepGround = null; _flushGround = null; _originHit = null; Vector3 up = _controller.up; Vector3 down = _controller.down; //碰撞检测起始位置 Vector3 o = origin + (up * _tolerance); //用于碰撞检测的Sphere要小一点 float smallerRadius = _controller.radius * 0.9f; RaycastHit hit; //向正下方投射Sphere看是是否碰撞到物体了 if (Physics.SphereCast(o, smallerRadius, down, out hit, Mathf.Infinity, _walkableLayer, _triggerInteraction)) { float standAngle = 0; float slopeLimit = 0; //拿到地面物体的碰撞属性 collisionAttribute = hit.collider.GetComponent <GroundCollisionAttribute>(); if (collisionAttribute != null) { standAngle = collisionAttribute.StandAngle; slopeLimit = collisionAttribute.SlopeLimit; } else { standAngle = GroundCollisionAttribute.DEFAULT_STAND_ANGLE; slopeLimit = GroundCollisionAttribute.DEFAULT_SLOPE_LIMIT; } _originHit = new GroundHit(hit.point, hit.normal, hit.distance); //检测碰撞到是不是真正的地面(因为通过投射Sphere检测到的碰撞物体的法线是一个差值,需要得到地面的实际碰撞信息) SimulateSphereCast(hit.normal, out hit); _primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); transform = hit.transform; //将碰撞点投射到控制器位置所在的平面,如果里控制器位置的距离足够小,表示碰撞到的是一个平坦的平面 if (Vector3.Distance(Math3d.ProjectPointOnPlane(_controller.up, _controller.worldPosition, hit.point), _controller.worldPosition) < _tinyTolerance) { return; } Vector3 toCenter = Math3d.ProjectVectorOnPlane(up, (_controller.worldPosition - hit.point).normalized * _tinyTolerance); Vector3 awayFromCenter = Quaternion.AngleAxis(-80.0f, Vector3.Cross(toCenter, _controller.up)) * -toCenter; Vector3 nearPoint = hit.point + toCenter + (_controller.up * _tolerance); Vector3 farPoint = hit.point + (awayFromCenter * 3); RaycastHit nearHit; RaycastHit farHit; Physics.Raycast(nearPoint, _controller.down, out nearHit, Mathf.Infinity, _walkableLayer, _triggerInteraction); Physics.Raycast(farPoint, _controller.down, out farHit, Mathf.Infinity, _walkableLayer, _triggerInteraction); _nearGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); _farGround = new GroundHit(farHit.point, farHit.normal, farHit.distance); if (Vector3.Angle(hit.normal, _controller.up) > standAngle) {//碰撞到的面是了一个陡坡或墙(碰撞面的法线与控制器正上方向的夹角大于设置的标准角度) //计算平行于碰撞表面且向下的向量 Vector3 r = Vector3.Cross(hit.normal, _controller.down); Vector3 v = Vector3.Cross(r, hit.normal); Vector3 flushOrigin = hit.point + hit.normal * _tolerance; RaycastHit flushHit; //沿着碰撞面向下发射射线检测碰撞的表面 if (Physics.Raycast(flushOrigin, v, out flushHit, Mathf.Infinity, _walkableLayer, _triggerInteraction)) { RaycastHit forTruethfulNormal; //校正法线 if (SimulateSphereCast(flushHit.normal, out forTruethfulNormal)) { //_primaryGround = new GroundHit(forTruethfulNormal.point, forTruethfulNormal.normal, forTruethfulNormal.distance); _flushGround = new GroundHit(forTruethfulNormal.point, forTruethfulNormal.normal, forTruethfulNormal.distance); } } } //// If we are currently standing on a ledge then the face nearest the center of the //// controller should be steep enough to be counted as a wall. Retrieve the ground //// it is connected to at it's base, if there exists any //if (Vector3.Angle(nearHit.normal, up) > standAngle || nearHit.distance > _tolerance) //{ // // We contacted the wall of the ledge, rather than the landing. Raycast down // // the wall to retrieve the proper landing // if (Vector3.Angle(nearHit.normal, up) > standAngle) // { // // Retrieve a vector pointing down the slope // Vector3 r = Vector3.Cross(nearHit.normal, down); // Vector3 v = Vector3.Cross(r, nearHit.normal); // RaycastHit stepHit; // if (Physics.Raycast(nearPoint, v, out stepHit, Mathf.Infinity, _walkableLayer, _triggerInteraction)) // { // _stepGround = new GroundHit(stepHit.point, stepHit.normal, stepHit.distance); // } // } // else // { // _stepGround = new GroundHit(nearHit.point, nearHit.normal, nearHit.distance); // } //} } else if (Physics.Raycast(o, down, out hit, Mathf.Infinity, _walkableLayer, _triggerInteraction)) { //拿到地面物体的碰撞属性 collisionAttribute = hit.collider.GetComponent <GroundCollisionAttribute>(); RaycastHit sphereHit; if (SimulateSphereCast(hit.normal, out sphereHit)) { _primaryGround = new GroundHit(sphereHit.point, sphereHit.normal, sphereHit.distance); } else { _primaryGround = new GroundHit(hit.point, hit.normal, hit.distance); } } else { Debug.LogError("Not found ground!"); } }
private void clearGround() { Ground = null; }