Comments (2)
I can see how the edge colliders could cause the issue you are seeing. The fix looks like it should do the trick. I'll push the changes in a little bit. Feel free to give it a try when the fix goes live and let me know if it takes care of the issue for you.
from charactercontroller2d.
cheers. I tested the fix a bit and had to adjust it so the character doesn't lose velocity when bumping into another edgecollider edge. Rather than setting the character to the first raycast hit point, I now send another ray along the next edge with the remaining target length. Also, in order to do the raycast test properly, I had to pass in the initial ray cast origin from the horizontal move method:
// call from moveHorizontally(ref Vector3 deltaMovement)
if (handleHorizontalSlope(ref deltaMovement, Vector2.Angle(_raycastHit.normal, Vector2.up), _raycastHit.point))
// handleHorizontalSlope method
private bool handleHorizontalSlope(ref Vector3 deltaMovement, float angle, Vector2 horizontalRaycastHit)
{
// disregard 90 degree angles (walls)
if (Mathf.RoundToInt(angle) == 90)
{
return false;
}
// if we can walk on slopes and our angle is small enough we need to move up
if (angle < slopeLimit)
{
// we only need to adjust the deltaMovement if we are not jumping
// TODO: this uses a magic number which isn't ideal!
if (deltaMovement.y < jumpingThreshold)
{
// apply the slopeModifier to slow our movement up the slope
var slopeModifier = slopeSpeedMultiplier.Evaluate(angle);
Vector2 rayOrigin = deltaMovement.x > 0
? new Vector2(horizontalRaycastHit.x - .1f, horizontalRaycastHit.y)
: new Vector2(horizontalRaycastHit.x + .1f, horizontalRaycastHit.y); // Note (Roman): added/subtracted .1f to make sure we stay on the same side
Vector2 currentdelta = Vector2.zero;
Vector2 targetDelta = new Vector2();
// we dont set collisions on the sides for this since a slope is not technically a side collision
// smooth y movement when we climb. we make the y movement equivalent to the actual y location that corresponds
// to our new x location using our good friend Pythagoras
float targetMoveX = deltaMovement.x * slopeModifier;
float targetMoveMultiplier = targetMoveX >= 0 ? -1f : 1f;
targetDelta.x = targetMoveX;
targetDelta.y = Mathf.Abs(Mathf.Tan(angle * Mathf.Deg2Rad) * targetDelta.x);
RaycastHit2D raycastHit;
do
{
bool isGoingRight = targetDelta.x > 0;
// check whether we go through a wall, if so adjust...
if (collisionState.wasGroundedLastFrame)
raycastHit = Physics2D.Raycast(rayOrigin, targetDelta.normalized, targetDelta.magnitude, platformMask);
else
raycastHit = Physics2D.Raycast(rayOrigin, targetDelta.normalized, targetDelta.magnitude, platformMask & ~oneWayPlatformMask);
if (raycastHit)
{//we crossed an edge when using Pythagoras calculation, so we set the actual delta movement to the ray hit location
Vector2 raycastHitVector = (raycastHit.point - rayOrigin);
currentdelta += raycastHitVector;
targetMoveX = targetMoveX + Mathf.Abs(currentdelta.x) * targetMoveMultiplier;
// we have adjusted the delta, now do the same thing again...
angle = Vector2.Angle(raycastHit.normal, Vector2.up);
if (angle < slopeLimit)
{
rayOrigin = rayOrigin + currentdelta;
targetDelta.x = targetMoveX;
targetDelta.y = Mathf.Abs(Mathf.Tan(angle * Mathf.Deg2Rad) * targetDelta.x);
}
else
{
Logger.Trace(TRACE_TAG, "handleHorizontalSlope -> slope limit exceeded after hit.");
break; // exit here
}
}
else
{
currentdelta += targetDelta;
Logger.Trace(TRACE_TAG, "handleHorizontalSlope -> no hit; final delta movement: {0}, final new position: {1}"
, currentdelta
, this.transform.position + new Vector3(currentdelta.x, currentdelta.y));
}
}
while (raycastHit);
deltaMovement.y = currentdelta.y;
deltaMovement.x = currentdelta.x;
_isGoingUpSlope = true;
collisionState.below = true;
collisionState.lastTimeGrounded = Time.time;
}
}
else // too steep. get out of here
{
deltaMovement.x = 0;
}
return true;
}
Also, I ran into another problem which is probably an edge case and therefore my fix probably isn't needed. When going up a slope, the vertical hit test is performed by moving the character to the delta adjusted x position and then sending rays up. However, in some circumstances this would result it moving the character across the slope and then hitting the collider from the other side:
My workaround is that if _isGoingUpSlope, call another vert move method which sends the test rays along the delta vector:
private void moveVerticallyOnSlope(ref Vector3 deltaMovement)
{
var rayDistance = deltaMovement.magnitude + _skinWidth;
Vector3 rayDirection = deltaMovement.normalized;
var initialRayOrigin = _raycastOrigins.topLeft;
// if we are moving up, we should ignore the layers in oneWayPlatformMask
var mask = platformMask;
if (!collisionState.wasGroundedLastFrame)
mask &= ~oneWayPlatformMask;
for (var i = 0; i < totalVerticalRays; i++)
{
var ray = new Vector2(initialRayOrigin.x + i * _horizontalDistanceBetweenRays, initialRayOrigin.y);
DrawRay(ray, rayDirection * rayDistance, Color.red);
_raycastHit = Physics2D.Raycast(ray, rayDirection, rayDistance, mask);
if (_raycastHit)
{
// set our new deltaMovement and recalculate the rayDistance taking it into account
deltaMovement = _raycastHit.point - ray;
rayDistance = deltaMovement.magnitude;
// remember to remove the skinWidth from our deltaMovement
if (deltaMovement.x > 0)
{
deltaMovement -= new Vector3(rayDirection.x * _skinWidth, rayDirection.y * _skinWidth, 0f);
}
else
{
deltaMovement += new Vector3(rayDirection.x * _skinWidth, rayDirection.y * _skinWidth, 0f);
}
collisionState.above = true;
_raycastHitsThisFrame.Add(_raycastHit);
// we add a small fudge factor for the float operations here. if our rayDistance is smaller
// than the width + fudge bail out because we have a direct impact
if (rayDistance < _skinWidth + kSkinWidthFloatFudgeFactor)
break;
}
}
}
thanks again for all your work on this!
from charactercontroller2d.
Related Issues (20)
- SpriteShape incompatible?
- OneWayPlatforms not detected on slopes
- License ShareAlike requirements HOT 1
- Seemingly random clipping into walls and ground.
- Enemies should use CC2D as well? HOT 1
- Time Scale & Target Frame HOT 1
- inconsistent grounding detection HOT 4
- License prohibits using this asset in any commercial game HOT 1
- When pressing down on one way platforms doesn't fall
- "Not Grounded" when descending a slope towards a flat surface. HOT 1
- Unwanted collision for lower oneWayPlatforms HOT 1
- Character springs very high into the air
- Launched in opposite direction when colliding exactly on an edge
- Call to Move should be moved from Update to FixedUpdate
- Any plan for ECS version?
- warpToGrounded doesn't seem to be used? HOT 1
- when you run and jump it can push you back when you hit the floor or the ground HOT 1
- Elevator glitch? HOT 2
- Warp to ground freeze Unity HOT 2
- support polygon collider
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from charactercontroller2d.