void GenerateColls(Collision col, bool resetCount) { if (resetCount) { mCollCount = 0; } Vector3 up = dirHolder.up; for (int i = 0, max = col.contacts.Length; i < max; i++) { if (mCollCount >= maxColls) { Debug.LogWarning("Ran out of collideInfo"); break; } ContactPoint contact = col.contacts[i]; Collider whichColl = col.collider;// contact.thisCollider != collider ? contact.thisCollider : contact.otherCollider; Vector3 n = contact.normal; Vector3 p = contact.point; CollisionFlags cf = GenCollFlag(up, contact); //check if already exists int ind = -1; for (int j = 0; j < mCollCount; j++) { CollideInfo inf = mColls[j]; if (inf.collider == whichColl) { //if(cf == CollisionFlags.None) //cf = GenCollFlag(up, contact); if (inf.flag == cf) { ind = j; break; } } } CollideInfo newInfo; if (ind == -1) { newInfo = mColls[mCollCount]; mCollCount++; } else { newInfo = mColls[ind]; } newInfo.collider = whichColl; newInfo.contactPoint = p; newInfo.normal = n; newInfo.flag = cf; } }
protected virtual void Awake() { mBody = GetComponent <Rigidbody>(); mColls = new CollideInfo[maxColls]; for (int i = 0; i < maxColls; i++) { mColls[i] = new CollideInfo(); } mGravCtrl = GetComponent <GravityController>(); //mTopBottomColCos = Mathf.Cos(sphereCollisionAngle * Mathf.Deg2Rad); mSlopLimitCos = Mathf.Cos(slopLimit * Mathf.Deg2Rad); mAboveLimitCos = Mathf.Cos(aboveLimit * Mathf.Deg2Rad); mColl = GetComponent <Collider>(); if (mColl != null) { if (mColl is SphereCollider) { mRadius = ((SphereCollider)mColl).radius; } else if (mColl is CapsuleCollider) { mCapsuleColl = mColl as CapsuleCollider; mRadius = mCapsuleColl.radius; } } mDefaultSpeedCap = speedCap; }
void OnCollisionStay2D(Collision2D col) { //remove existing information with given collider for (int j = 0; j < mColls.Count; j++) { CollideInfo inf = mColls[j]; if (inf.collider == col.collider) { RemoveColl(j); j--; } } GenerateColls(col, false); //recalculate flags RefreshCollInfo(); if (collisionStayCallback != null) { collisionStayCallback(this, col); } /*if(pc != mCollCount) * Debug.Log("scount: " + mCollCount);*/ }
void OnCollisionExit2D(Collision2D col) { //foreach(ContactPoint cp in col.contacts) { //Debug.Log("out: " + cp.otherCollider.name + " n: " + cp.normal); //} //mCollCount = 0; //remove existing information with given collider for (int j = 0; j < mColls.Count; j++) { CollideInfo inf = mColls[j]; if (inf.collider == col.collider) { RemoveColl(j); j--; } } RefreshCollInfo(); if (collisionExitCallback != null) { collisionExitCallback(this, col); } //Debug.Log("exit count: " + mCollCount); }
protected virtual void RefreshCollInfo() { mCollFlags = CollisionFlags.None; mCollLayerMask = 0; mIsSlopSlide = false; bool groundNoSlope = false; //prevent slope slide if we are also touching a non-slidable ground (standing on the corner base of slope) Vector3 up = dirHolder.up; // for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if (inf.collider == null || inf.collider.gameObject == null || !inf.collider.gameObject.activeInHierarchy) { RemoveColl(i); i--; continue; } Vector3 n = inf.normal; CollisionFlags flag = inf.flag; mCollFlags |= inf.flag; if (flag == CollisionFlags.Below || flag == CollisionFlags.Sides) { //sliding if (!(slideDisable || groundNoSlope)) { float a = Vector3.Angle(up, n); mIsSlopSlide = a > slopLimit && a <= slideLimit; if (mIsSlopSlide) { //Debug.Log("a: " + a); mSlopNormal = n; } else if (flag == CollisionFlags.Below) { mIsSlopSlide = false; groundNoSlope = true; } } mCollLayerMask |= 1 << inf.collider.gameObject.layer; } } //no longer standing? if (!isGrounded) { mStanding = false; } }
void OnCollisionExit(Collision col) { //foreach(ContactPoint cp in col.contacts) { //Debug.Log("out: " + cp.otherCollider.name + " n: " + cp.normal); //} //mCollCount = 0; //remove existing information with given collider for (int j = 0; j < mCollCount; j++) { CollideInfo inf = mColls[j]; if (inf.collider == col.collider) { RemoveColl(j); j--; } } /*foreach(ContactPoint cp in col.contacts) { * Debug.Log("out: " + cp.otherCollider.name + " n: " + cp.normal); * }*/ //Debug.Log("exit: " + col.gameObject.name); //Vector3 up = dirHolder.up; /*foreach(ContactPoint contact in col.contacts) { * Collider whichColl = contact.thisCollider != collider ? contact.thisCollider : contact.otherCollider; * //Vector3 n = contact.normal; * //Vector3 p = contact.point; * //CollisionFlags cf = CollisionFlags.None; * * for(int i = 0; i < mCollCount; i++) { * CollideInfo inf = mColls[i]; * if(inf.collider == whichColl) { * //if(cf == CollisionFlags.None) * //cf = GenCollFlag(up, contact); * * //if(inf.flag == cf) * RemoveColl(i); * } * } * }*/ RefreshCollInfo(); if (collisionExitCallback != null) { collisionExitCallback(this, col); } //Debug.Log("exit count: " + mCollCount); }
/// <summary> /// Get the first occurence of CollideInfo based on given flags /// </summary> public CollideInfo GetCollideInfo(CollisionFlags flags) { for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if ((inf.flag & flags) != 0) { return(inf); } } return(null); }
//return true if we moved public bool Move(Vector2 axis, float force) { //compute move direction Vector2 moveDelta = axis; mCurMoveDir = moveDelta.normalized; float maxSpeed = 0.0f; //allow for moving diagonally downwards //TODO: test for non-platformer if (isGrounded) { for (int i = 0; i < mColls.Count; i++) { CollideInfo inf = mColls[i]; if (inf.flag == CollisionFlags.Below) { Vector2 moveDeltaX = new Vector2(moveDelta.x, 0f); moveDeltaX = M8.MathUtil.Slide(moveDeltaX, inf.normal); moveDelta = new Vector2(moveDeltaX.x, moveDeltaX.y + moveDelta.y); mCurMoveDir = moveDelta.normalized; break; } } maxSpeed = moveMaxSpeed; } else { maxSpeed = airMaxSpeed; } #if MATE_PHYSICS_DEBUG M8.DebugUtil.DrawArrow(transform.position, mCurMoveDir); #endif //check if we can move based on speed or if going against new direction bool canMove = CanMove(mCurMoveDir, maxSpeed * moveScale); if (canMove) { //M8.Debug. mBody.AddForce(moveDelta * force * moveScale); return(true); } return(false); }
public bool TryGetCollideInfo(Collider col, out CollideInfo inf) { for (int i = 0; i < mColls.Count; i++) { if (mColls[i].collider == col) { inf = mColls[i]; return(true); } } inf = new CollideInfo(); return(false); }
/// <summary> /// Get the first occurence of CollideInfo based on given flags /// </summary> public bool TryGetCollideInfo(CollisionFlags flags, out CollideInfo inf) { for (int i = 0; i < mColls.Count; i++) { CollideInfo _inf = mColls[i]; if ((_inf.flag & flags) != 0) { inf = _inf; return(true); } } inf = new CollideInfo(); return(false); }
void Rule_Shot() { if (newRule) { SFX("Rayman2/Rayman/shoot/simple").SetVolume(0.625f); SFX("Rayman2/Rayman/shoot/simple").Play(0.05f); SpawnParticle(true, "FistTrail1", LumType.Yellow); bounces = 0; } if (DistTo(rayman) > 40) { SetRule("Fizzle"); return; } r = Raycast(vel, 1); if (r.Any) { if (++bounces >= 3) { Kill(); } else { if (r.hitPerso != null) { r.hitPerso.Damage(damage); Remove(); return; } Bounce3D(r.hit.normal); FaceVel2D(false); BounceFX(); var t = FindTarget(20, 45); if (t != null) { vel = vel.magnitude * Vec(t); } } } }
protected void RemoveColl(int ind) { if (mCollCount > 0) { int lastInd = mCollCount - 1; if (ind == lastInd) { mColls[ind].collider = null; mColls[ind].flag = CollisionFlags.None; } else { CollideInfo removeInf = mColls[ind]; removeInf.collider = null; removeInf.flag = CollisionFlags.None; CollideInfo lastInf = mColls[lastInd]; mColls[ind] = lastInf; mColls[lastInd] = removeInf; } mCollCount--; } }
//bool allowTest = false; void testPath() { // if (allowTest == false) // return; if (nextNode == null) { return; } Vector3 distVec = nextNode.goal.point - transform.position; float awayOrNearDot = Vector3.Dot(speedVec, distVec.normalized); if (awayOrNearDot < 0) //is away { return; } float collideTime = distVec.magnitude / speed; CollideInfo info = CollideManager.collideInfo; if (info.minCollideTime == -1 || collideTime < info.minCollideTime) { info.minCollideTime = collideTime; info.node = nextNode; info.reachGoalobj = this; info.collidePoint = Vector3.zero; info.collideSurfaceP0 = Vector3.zero; info.collideSurfaceP1 = Vector3.zero; info.intersectPoint = Vector3.zero; info.vertex = null; info.surface = null; } //Debug.Log ( collideTime ); }
//collide will ocur after this time public void vertexContactSurface(VERTEX vertex, SURFACE surface) { //ignore vertexs which is back to surface bool isFacing = false; for (int i = 0; i < vertex.normals.Count; i++) { Vector3 vertexNormal = vertex.normals[i].direct; float facingDot = Vector3.Dot(vertexNormal, surface.normal.direct); float threshold = 0.000001f; if (facingDot > -threshold && facingDot < threshold) { facingDot = 0; } if (facingDot < 0) { isFacing = true; break; } } if (!isFacing) { return; } //check if under surface Vector3 beginVec = surface.points[0].pos - vertex.pos; float dist = Vector3.Dot(beginVec, surface.normal.direct); if (dist > 0)//ignore the surfaces which is back to vertex { return; } // relateVec intersect surface Vector3 perpendicularVec = surface.normal.direct * dist; float angle = Vector3.Angle(-relateVec, perpendicularVec); if (angle >= 90)//parallel { return; } float length = Mathf.Abs(dist) / Mathf.Cos(Mathf.Deg2Rad * angle); Vector3 intersectPoint = vertex.pos - relateVec.normalized * length; //contactsurface float collideTime = length / relateVec.magnitude; surface.belongToObj.computeGlobalSpeed(); Vector3 surfaceGlobalSpeedVec = surface.belongToObj.globalSpeedVec; Vector3 collideSurfaceP0 = surface.points[0].pos + surfaceGlobalSpeedVec * collideTime; Vector3 collideSurfaceP1 = surface.points[1].pos + surfaceGlobalSpeedVec * collideTime; //Vector3 collideSurfaceNormal = surface.normal.direct; //check if in contact surface Vector3 collidePoint = vertex.pos + globalSpeedVec * collideTime; if (Math3D.isProjectInSurface(collidePoint, collideSurfaceP0, collideSurfaceP1)) //will contact in future { CollideInfo info = CollideManager.collideInfo; if (info.minCollideTime == -1 || collideTime < info.minCollideTime) { info.minCollideTime = collideTime; info.collidePoint = collidePoint; info.collideSurfaceP0 = collideSurfaceP0; info.collideSurfaceP1 = collideSurfaceP1; info.intersectPoint = intersectPoint; info.vertex = vertex; info.surface = surface; info.node = null; info.reachGoalobj = null; } } }
void GenerateColls(Collision2D col, bool resetCount) { if (resetCount) { mColls.Clear(); } Vector2 up = dirHolder.up; int contactCount = col.GetContacts(mContactPoints); for (int i = 0; i < contactCount; i++) { ContactPoint2D contact = mContactPoints[i]; Collider2D whichColl = col.collider;// contact.thisCollider != collider ? contact.thisCollider : contact.otherCollider; Vector2 n = contact.normal; Vector2 p = contact.point; CollisionFlags cf = GenCollFlag(up, contact); //check if already exists int ind = -1; for (int j = 0; j < mColls.Count; j++) { CollideInfo inf = mColls[j]; if (inf.collider == whichColl) { //if(cf == CollisionFlags.None) //cf = GenCollFlag(up, contact); if (inf.flag == cf) { ind = j; break; } } } var newCollInf = new CollideInfo() { collider = whichColl, contactPoint = p, normal = n, flag = cf, }; if (ind == -1) //add new { if (mColls.Count == mColls.Capacity) { mColls.Expand(); } mColls.Add(newCollInf); } else //update info { mColls[ind] = newCollInf; } } }
protected override void RefreshCollInfo() { //plank check, see if we need to ignore it if (plankLayer != 0 && !mPlankIsIgnore) { //check if there's a coll that is a plank bool plankFound = false; CollisionFlags plankCollFlag = CollisionFlags.None; for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if (inf.collider == null || inf.collider.gameObject == null || !inf.collider.gameObject.activeInHierarchy) { RemoveColl(i); i--; } else if (((1 << inf.collider.gameObject.layer) & plankLayer) != 0) { plankFound = true; plankCollFlag = inf.flag; if (plankCollFlag != CollisionFlags.Below) { RemoveColl(i); i--; } } } if (plankFound) { if (plankCollFlag == CollisionFlags.Below) { //check if we are ready to drop if (plankEnableDrop && mMoveYGround < 0.0f && Time.fixedTime - mMoveYGroundDownLastTime >= plankDropDelay) { SetPlankingIgnore(true); } } else { SetLocalVelocityToBody(); //revert rigidbody's velocity :P SetPlankingIgnore(true); } } else if (isGrounded && mMoveYGround < 0.0f) { mMoveYGround = 0.0f; } } base.RefreshCollInfo(); //bool isGroundColl = (mCollFlags & CollisionFlags.Below) != 0; if (mIsOnPlatform) { mCollFlags |= CollisionFlags.Below; mCollGroundLayerMask |= mIsOnPlatformLayerMask; } bool lastWallStick = mWallSticking; mWallSticking = false; if (isSlopSlide) { //Debug.Log("sliding"); mLastGround = false; mJumpCounter = jumpCounter; } //refresh wallstick else if (wallStick && !mJumpingWall && collisionFlags == CollisionFlags.Sides) { //check if we are going up if (!wallStickDownOnly || localVelocity.y <= 0.0f) { Vector3 up = dirHolder.up; if (collisionFlags == CollisionFlags.Sides) { for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if (inf.flag == CollisionFlags.Sides && (wallStickInvalidMask == 0 || ((1 << inf.collider.gameObject.layer) & wallStickInvalidMask) == 0)) { float a = Vector3.Angle(up, inf.normal); if (a >= 90.0f - wallStickAngleOfs && a <= 90.0f + wallStickAngleOfs) { //wallStickForce mWallStickCollInfo = inf; mWallStickSide = M8.MathUtil.CheckSide(mWallStickCollInfo.normal, dirHolder.up); mWallSticking = true; break; } } } } } if (mWallSticking) { if (wallStickPush) { if (CheckWallStickIn(moveSide)) { if (!mWallStickWaitInput) { //cancel horizontal movement Vector3 newVel = localVelocity; newVel.x = 0.0f; //reduce downward speed if (newVel.y < -wallStickDownSpeedCap) { newVel.y = -wallStickDownSpeedCap; } rigidbody.velocity = dirHolder.rotation * newVel; mWallStickLastTime = Time.fixedTime; mWallStickWaitInput = true; } mWallStickLastInputTime = Time.fixedTime; } else { bool wallStickExpired = Time.fixedTime - mWallStickLastInputTime > wallStickDelay; if (wallStickExpired) { mWallStickWaitInput = false; mWallSticking = false; } } } else { bool wallStickExpired = Time.fixedTime - mWallStickLastTime > wallStickDelay; //see if we are moving away if ((wallStickExpired && CheckWallStickMoveAway(moveSide))) { if (!mWallStickWaitInput) { mWallSticking = false; } } else if (!lastWallStick) { mWallStickWaitInput = true; mWallStickLastTime = Time.fixedTime; //cancel horizontal movement Vector3 newVel = localVelocity; newVel.x = 0.0f; //reduce downward speed if (newVel.y < -wallStickDownSpeedCap) { newVel.y = -wallStickDownSpeedCap; } rigidbody.velocity = dirHolder.rotation * newVel; } } } if (mWallSticking != lastWallStick) { if (mWallSticking) { mJump = false; lockDrag = false; } else { if (wallStickPush) { mWallStickWaitInput = false; } } } } if (mLastGround != isGrounded) { if (!mLastGround) { //Debug.Log("landed"); //mJump = false; //mJumpingWall = false; mJumpCounter = 0; if (localVelocity.y <= 0.0f) { if (landCallback != null) { landCallback(this); } } } else { //falling down? /*if(mJumpCounter <= 0) * mJumpCounter = 1;*/ mJumpLastTime = Time.fixedTime; mLastGroundTime = Time.fixedTime; } mLastGround = isGrounded; } }
//return true if we moved public bool Move(Quaternion dirRot, Vector3 forward, Vector3 right, Vector2 axis, float force) { //compute move direction Vector3 moveDelta = axis.y != 0.0f ? dirRot * forward * axis.y : Vector3.zero; if (axis.x != 0.0f) { moveDelta += dirRot * right * axis.x; } mCurMoveDir = moveDelta.normalized; float maxSpeed = 0.0f; //allow for moving diagonally downwards //TODO: test for non-platformer if (isGrounded) { for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if (inf.flag == CollisionFlags.Below) { moveDelta = M8.MathUtil.Slide(moveDelta, inf.normal); mCurMoveDir = moveDelta.normalized; break; } } maxSpeed = moveMaxSpeed; } else { maxSpeed = airMaxSpeed; } //check if we need to slide off walls /*foreach(KeyValuePair<Collider, CollideInfo> pair in mColls) { * if(pair.Value.flag == CollisionFlags.Sides) { * Vector3 colN = pair.Value.normal; * if(Vector3.Dot(mCurMoveDir, colN) < 0.0f) { * moveDelta = M8.MathUtil.Slide(mCurMoveDir, colN); * moveDelta.Normalize(); * mCurMoveDir = moveDelta; * } * } * }*/ #if MATE_PHYSICS_DEBUG M8.DebugUtil.DrawArrow(transform.position, mCurMoveDir); #endif //check if we can move based on speed or if going against new direction bool canMove = CanMove(mCurMoveDir, maxSpeed * moveScale); if (canMove) { //M8.Debug. mBody.AddForce(moveDelta * force * moveScale); return(true); } return(false); }
void Rule_Air() { #region Rule col.groundDepth = 0; col.UpdateGroundCollision(); if (newRule) { liftOffVel = velXZ.magnitude; } if (col.ground.AnyGround && velY <= 0) { velY = 0; SetRule("Ground"); return; } else if (col.ground.Slide) { SetRule("Sliding"); return; } else if (col.ground.Water && velY < 0 && !col.waterIsShallow) { SetRule("Swimming"); return; } else if (!t_blockHang.active && col.ceiling.HangableCeiling) { SetRule("Hanging"); return; } if (jumping) { gravity = -20; if (velY < jumpCutoff) { jumping = false; } } else { gravity = -30; } // Ledgegrab var lh = Raycast(forward * 2 + upward * 3, -upward, 1); if (lh.AnyGround) { float dist = DistTo(lh); CollideInfo ledge = new CollideInfo(); for (float d = dist; d > 0; d -= 0.05f) { var lh2 = RayCollider.Raycast(pos + d * Vec2D(pos, lh.hit.point), -upward, 2); if (!lh2.AnyGround) { ledge = lh2; break; } } if (ledge.AnyGround) { this.ledge = ledge; SetRule("Ledgegrab"); return; } } ApplyGravity(); if (helic) { if (superHelicAscend) { superHelicRev = Mathf.Lerp(superHelicRev, 42, dt * 45); } else { superHelicRev = Mathf.Lerp(superHelicRev, 0, dt * 1); } SFX("Rayman2/Rayman/helic").asrc.pitch = 1 + superHelicRev / 300; anim.SetSpeed(30 + superHelicRev / 7); SetFriction(6.5f, hasSuperHelic ? 2.6f : 7.5f); velY += dt * superHelicRev; velY = Mathf.Clamp(velY, hasSuperHelic ? -25 : -5, 5); selfJump = false; } else { if (slideJump) { SetFriction(0.1f, 0); } else { SetFriction(5, 0); } moveSpeed = 10; } MoveOrStrafe(6, helic ? 5 : -1); AlignY(10); if (pos.y < startPos.y - 1100) { SetRule("Falling"); } #endregion #region Animation if (helic) { anim.Set(Anim.HelicEnable, 1); } else if (liftOffVel < 5 || !selfJump) { if (velY > 5 + jumpLiftOffVelY) { anim.Set(Anim.JumpIdleLoop, 0); } else { if (newRule) { anim.Set(Anim.FallIdleLoop, 0); } else { anim.Set(Anim.FallIdleStart, 1); } } } else { if (velY > 5 + jumpLiftOffVelY) { anim.Set(Anim.JumpRunLoop, 0); } else { if (newRule) { anim.Set(Anim.FallRunLoop, 0); } else { anim.Set(Anim.FallRunStart, 1); } } } #endregion }
void OnInputJump(InputManager.Info dat) { //jumpWall if (dat.state == InputManager.State.Pressed) { if (isUnderWater || isOnLadder) { mJump = true; } else if (jumpWall && collisionFlags == CollisionFlags.Sides) { bool found = false; CollideInfo inf = new CollideInfo(); for (int i = 0; i < mCollCount; i++) { CollideInfo cInf = mColls[i]; if (cInf.flag == CollisionFlags.Sides) { if (Vector3.Angle(dirHolder.forward, cInf.normal) > 120.0f) { inf = cInf; found = true; break; } } } if (found) { Vector3 jumpDir = inf.normal + dirHolder.up; if (jumpImpulse > 0.0f) { ClearCollFlags(); mBody.drag = airDrag; mBody.AddForce(jumpDir * jumpImpulse, ForceMode.Impulse); } mJump = true; mJumpLastTime = Time.fixedTime; float a = M8.MathUtil.AngleForwardAxisDir(dirHolder.worldToLocalMatrix, Vector3.forward, inf.normal); dirHolder.rotation *= Quaternion.AngleAxis(a, Vector3.up); EyeOrient(); //TurnTo(inf.normal); } } else if (!mJump) { if (isUnderWater || isOnLadder) { mJump = true; } else if (!isSlopSlide) { if (isGrounded) { if (jumpImpulse > 0.0f) { ClearCollFlags(); mBody.drag = airDrag; mBody.AddForce(dirHolder.up * jumpImpulse, ForceMode.Impulse); } mJump = true; mJumpLastTime = Time.fixedTime; } } } } else if (dat.state == InputManager.State.Released) { mJump = false; } }
protected override void RefreshCollInfo() { //plank check, see if we need to ignore it if(plankLayer != 0 && !mPlankIsIgnore) { //check if there's a coll that is a plank bool plankFound = false; CollisionFlags plankCollFlag = CollisionFlags.None; for(int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if(inf.collider == null || inf.collider.gameObject == null || !inf.collider.gameObject.activeInHierarchy) { RemoveColl(i); i--; } else if(((1 << inf.collider.gameObject.layer) & plankLayer) != 0) { plankFound = true; plankCollFlag = inf.flag; if(plankCollFlag != CollisionFlags.Below) { RemoveColl(i); i--; } } } if(plankFound) { if(plankCollFlag == CollisionFlags.Below) { //check if we are ready to drop if(plankEnableDrop && mMoveYGround < 0.0f && Time.fixedTime - mMoveYGroundDownLastTime >= plankDropDelay) { SetPlankingIgnore(true); } } else { SetLocalVelocityToBody(); //revert rigidbody's velocity :P SetPlankingIgnore(true); } } else if(isGrounded && mMoveYGround < 0.0f) { mMoveYGround = 0.0f; } } base.RefreshCollInfo(); //bool isGroundColl = (mCollFlags & CollisionFlags.Below) != 0; if(mIsOnPlatform) { mCollFlags |= CollisionFlags.Below; mCollGroundLayerMask |= mIsOnPlatformLayerMask; } bool lastWallStick = mWallSticking; mWallSticking = false; if(isSlopSlide) { //Debug.Log("sliding"); mLastGround = false; mJumpCounter = jumpCounter; } //refresh wallstick else if(wallStick && !mJumpingWall && collisionFlags == CollisionFlags.Sides) { //check if we are going up if(!wallStickDownOnly || localVelocity.y <= 0.0f) { Vector3 up = dirHolder.up; if(collisionFlags == CollisionFlags.Sides) { for(int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if(inf.flag == CollisionFlags.Sides && (wallStickInvalidMask == 0 || ((1<<inf.collider.gameObject.layer) & wallStickInvalidMask) == 0)) { float a = Vector3.Angle(up, inf.normal); if(a >= 90.0f - wallStickAngleOfs && a <= 90.0f + wallStickAngleOfs) { //wallStickForce mWallStickCollInfo = inf; mWallStickSide = M8.MathUtil.CheckSide(mWallStickCollInfo.normal, dirHolder.up); mWallSticking = true; break; } } } } } if(mWallSticking) { if(wallStickPush) { if(CheckWallStickIn(moveSide)) { if(!mWallStickWaitInput) { //cancel horizontal movement Vector3 newVel = localVelocity; newVel.x = 0.0f; //reduce downward speed if(newVel.y < -wallStickDownSpeedCap) newVel.y = -wallStickDownSpeedCap; rigidbody.velocity = dirHolder.rotation * newVel; mWallStickLastTime = Time.fixedTime; mWallStickWaitInput = true; } mWallStickLastInputTime = Time.fixedTime; } else { bool wallStickExpired = Time.fixedTime - mWallStickLastInputTime > wallStickDelay; if(wallStickExpired) { mWallStickWaitInput = false; mWallSticking = false; } } } else { bool wallStickExpired = Time.fixedTime - mWallStickLastTime > wallStickDelay; //see if we are moving away if((wallStickExpired && CheckWallStickMoveAway(moveSide))) { if(!mWallStickWaitInput) { mWallSticking = false; } } else if(!lastWallStick) { mWallStickWaitInput = true; mWallStickLastTime = Time.fixedTime; //cancel horizontal movement Vector3 newVel = localVelocity; newVel.x = 0.0f; //reduce downward speed if(newVel.y < -wallStickDownSpeedCap) newVel.y = -wallStickDownSpeedCap; rigidbody.velocity = dirHolder.rotation * newVel; } } } if(mWallSticking != lastWallStick) { if(mWallSticking) { mJump = false; lockDrag = false; } else { if(wallStickPush) mWallStickWaitInput = false; } } } if(mLastGround != isGrounded) { if(!mLastGround) { //Debug.Log("landed"); //mJump = false; //mJumpingWall = false; mJumpCounter = 0; if(localVelocity.y <= 0.0f) { if(landCallback != null) landCallback(this); } } else { //falling down? /*if(mJumpCounter <= 0) mJumpCounter = 1;*/ mJumpLastTime = Time.fixedTime; mLastGroundTime = Time.fixedTime; } mLastGround = isGrounded; } }
protected override void RefreshCollInfo() { base.RefreshCollInfo(); //bool isGroundColl = (mCollFlags & CollisionFlags.Below) != 0; if (mIsOnPlatform) { mCollFlags |= CollisionFlags.Below; mCollGroundLayerMask |= mIsOnPlatformLayerMask; } bool lastWallStick = mWallSticking; mWallSticking = false; if (isSlopSlide) { //Debug.Log("sliding"); mLastGround = false; mJumpCounter = jumpCounter; } //refresh wallstick else if (wallStick && !mJumpingWall && collisionFlags == CollisionFlags.Sides) { Vector3 up = dirHolder.up; if (collisionFlags == CollisionFlags.Sides) { for (int i = 0; i < mCollCount; i++) { CollideInfo inf = mColls[i]; if (inf.flag == CollisionFlags.Sides) { float a = Vector3.Angle(up, inf.normal); if (a >= 90.0f - wallStickAngleOfs && a <= 90.0f + wallStickAngleOfs) { //wallStickForce mWallStickCollInfo = inf; mWallStickSide = M8.MathUtil.CheckSide(mWallStickCollInfo.normal, dirHolder.up); mWallSticking = true; mJump = false; lockDrag = false; break; } } } } if (mWallSticking) { bool wallStickExpired = Time.fixedTime - mWallStickLastTime > wallStickDelay; //see if we are moving away if (wallStickExpired && CheckWallStickMoveAway(moveSide)) { if (!mWallStickWaitInput) { mWallSticking = false; } } else if (!lastWallStick) { mWallStickWaitInput = true; mWallStickLastTime = Time.fixedTime; //cancel horizontal movement Vector3 newVel = localVelocity; newVel.x = 0.0f; //reduce downward speed if (newVel.y < -wallStickDownSpeedCap) { newVel.y = -wallStickDownSpeedCap; } rigidbody.velocity = dirHolder.rotation * newVel; } } } if (mLastGround != isGrounded) { if (!mLastGround) { //Debug.Log("landed"); //mJump = false; //mJumpingWall = false; mJumpCounter = 0; if (landCallback != null) { landCallback(this); } } else { //falling down? /*if(mJumpCounter <= 0) * mJumpCounter = 1;*/ mJumpLastTime = Time.fixedTime; } mLastGround = isGrounded; } }