player collision fixes

This commit is contained in:
GoaLitiuM
2021-09-05 00:47:50 +03:00
parent 26221be7a9
commit a49be3af7c
2 changed files with 133 additions and 26 deletions

View File

@@ -1,17 +1,15 @@
{
"ID": "af2e52554f7faed7b4937181dd22d166",
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
"EngineBuild": 6222,
"EngineBuild": 6224,
"Data": {
"MaxAssetsPerPackage": 4096,
"MaxPackageSizeMB": 1024,
"ContentKey": 0,
"ForDistribution": false,
"SkipPackaging": false,
"AdditionalAssets": [
"54a1ff4a42af9f018234f7b39b1366b3",
"1ef4565844a4b36cdfda54b51f338c77"
],
"AdditionalAssets": [],
"AdditionalAssetFolders": [],
"ShadersNoOptimize": false,
"ShadersGenerateDebugData": false,
"Presets": [
@@ -22,7 +20,10 @@
"Name": "Win64",
"Output": "Output\\Windows",
"Platform": 2,
"Mode": 1
"Mode": 1,
"CustomDefines": null,
"PreBuildAction": null,
"PostBuildAction": null
}
]
},
@@ -33,7 +34,10 @@
"Name": "Win64",
"Output": "Output\\WindowsRelease",
"Platform": 2,
"Mode": 2
"Mode": 2,
"CustomDefines": null,
"PreBuildAction": null,
"PostBuildAction": null
}
]
}

View File

@@ -39,7 +39,8 @@ namespace Game
private InputEvent onExit = new InputEvent("Exit");
private const float collisionMargin = 0.031f * 1.666f;
// FIXME, should be much smaller but needed to avoid issues with box collider edges against brush edges diagonally
private const float collisionMargin = 0.031f * 1.666f * 1.85f;
private const float slopeNormal = 0.7f;
private Actor rootActor;
@@ -102,16 +103,8 @@ namespace Game
viewRoll = initialEulerAngles.Z;
}
/// <summary>
/// Sweeps the player rigidbody in world and returns geometry which was hit during the trace.
/// </summary>
/// <param name="start">Start position</param>
/// <param name="end">End position</param>
/// <returns></returns>
private TraceInfo TracePlayer(Vector3 start, Vector3 end)
private bool SweepPlayerCollider(Vector3 start, Vector3 end, out RayCastHit[] hits)
{
TraceInfo traceInfo = new TraceInfo();
Vector3 delta = end - start;
float maxDistance = delta.Length;
Vector3 direction = delta.Normalized;
@@ -126,7 +119,7 @@ namespace Game
colliderActor = capsuleCollider;
collided = Physics.CapsuleCastAll(start,
capsuleCollider.Radius, capsuleCollider.Height,
direction, out traceInfo.hitInfos, capsuleCollider.Orientation, maxDistance,
direction, out hits, capsuleCollider.Orientation, maxDistance,
uint.MaxValue,
false);
}
@@ -135,7 +128,7 @@ namespace Game
colliderActor = meshCollider;
collided = Physics.ConvexCastAll(start,
meshCollider.CollisionData, meshCollider.Scale,
direction, out traceInfo.hitInfos, meshCollider.Orientation, maxDistance,
direction, out hits, meshCollider.Orientation, maxDistance,
uint.MaxValue,
false);
}
@@ -144,10 +137,91 @@ namespace Game
colliderActor = boxCollider;
collided = Physics.BoxCastAll(start,
boxCollider.OrientedBox.Extents,
direction, out traceInfo.hitInfos, boxCollider.Orientation, maxDistance, uint.MaxValue,
direction, out hits, boxCollider.Orientation, maxDistance,
uint.MaxValue,
false);
}
else
{
throw new Exception("Player does not have a collider");
}
return collided;
}
private bool SweepPlayerCollider(Vector3 position, out PhysicsColliderActor[] colliders)
{
bool collided = false;
var capsuleCollider = Actor.GetChild<CapsuleCollider>();
var boxCollider = Actor.GetChild<BoxCollider>();
var meshCollider = Actor.GetChild<MeshCollider>();
PhysicsColliderActor colliderActor = null;
if (capsuleCollider && capsuleCollider.IsActive)
{
colliderActor = capsuleCollider;
collided = Physics.OverlapCapsule(position,
capsuleCollider.Radius, capsuleCollider.Height,
out colliders, capsuleCollider.Orientation,
uint.MaxValue,
false);
}
else if (meshCollider && meshCollider.IsActive)
{
colliderActor = meshCollider;
collided = Physics.OverlapConvex(position,
meshCollider.CollisionData, meshCollider.Scale,
out colliders, meshCollider.Orientation,
uint.MaxValue,
false);
}
else if (boxCollider && boxCollider.IsActive)
{
colliderActor = boxCollider;
collided = Physics.OverlapBox(position,
boxCollider.OrientedBox.Extents,
out colliders, boxCollider.Orientation,
uint.MaxValue,
false);
}
else
{
throw new Exception("Player does not have a collider");
}
if (collided)
{
List<PhysicsColliderActor> collidersFiltered = new List<PhysicsColliderActor>();
foreach (var collider in colliders)
{
if (collider.Parent == Actor)
continue;
collidersFiltered.Add(collider);
}
colliders = collidersFiltered.ToArray();
if (colliders.Length == 0)
collided = false;
}
return collided;
}
/// <summary>
/// Sweeps the player rigidbody in world and returns geometry which was hit during the trace.
/// </summary>
/// <param name="start">Start position</param>
/// <param name="end">End position</param>
/// <returns></returns>
private TraceInfo TracePlayer(Vector3 start, Vector3 end)
{
TraceInfo traceInfo = new TraceInfo();
Vector3 delta = end - start;
float maxDistance = delta.Length;
Vector3 direction = delta.Normalized;
bool collided = SweepPlayerCollider(start, end, out traceInfo.hitInfos);
if (collided)
{
List<RayCastHit> hitInfosFiltered = new List<RayCastHit>();
@@ -155,7 +229,9 @@ namespace Game
closest.Distance = float.MaxValue;
foreach (var hitInfo in traceInfo.hitInfos)
{
if (hitInfo.Collider == colliderActor)
//if (hitInfo.Collider == colliderActor)
// continue;
if (hitInfo.Collider.Parent == Actor)
continue;
hitInfosFiltered.Add(hitInfo);
@@ -164,8 +240,27 @@ namespace Game
closest = hitInfo;
}
if (hitInfosFiltered.Count == 0)
if (hitInfosFiltered.Count == 0 /*|| closest.Distance == float.MaxValue*/)
collided = false; // self-collision?
/*else if (closest.Distance == float.MaxValue)
{
bool startSolid = SweepPlayerCollider(start, out PhysicsColliderActor[] colliders);
if (startSolid)
{
traceInfo.hitInfos = hitInfosFiltered.ToArray();
traceInfo.fraction = 0f;
traceInfo.hitNormal = Vector3.Zero;
traceInfo.hitPosition = start;
traceInfo.endPosition = start;
traceInfo.startSolid = true;
if (delta.Y >= 0f)
Console.Print("ovr: " + colliders[0].Parent.Name);
}
else
collided = false;
}*/
else //if (closest.Distance > 0f)
{
if (closest.Distance == float.MaxValue)
@@ -186,6 +281,9 @@ namespace Game
if (traceInfo.fraction == 0f && maxDistance > 0f)
traceInfo.startSolid = true;
//if (delta.Y >= 0f)
// Console.Print("col: " + closest.Collider.Parent.Name + ", " + closest.Distance.ToString("G9"));
}
/*else
{
@@ -280,7 +378,7 @@ namespace Game
else if (traceDown.fraction > 0f)
position = traceDown.endPosition;
// add some margin from the ground in order to avoid getting stuck
// add some margin from the ground in order to avoid getting stuck after stepping up
if (traceDown.fraction < 1f)
position.Y += collisionMargin;
@@ -289,7 +387,7 @@ namespace Game
var d2 = -Vector3.Dot(Physics.Gravity.Normalized, originalPosition);
if (d1 < d2)
{
Console.Print("no stepping 2, " + d1 + " < " + d2);
//Console.Print("no stepping 2, " + d1 + " < " + d2);
position = slidePosition;
velocity = slideVelocity;
return slideMoveHit;
@@ -306,7 +404,7 @@ namespace Game
//if ((stepPosition2 - originalPosition).Length < (slidePosition2 - originalPosition).Length)
if ((slidePosition2 - originalPosition).Length >= (stepPosition2 - originalPosition).Length)
{
Console.Print("no stepping 3");
//Console.Print("no stepping 3");
position = slidePosition;
velocity = slideVelocity;
return slideMoveHit;
@@ -425,6 +523,7 @@ namespace Game
// push off slightly away from the walls to not get stuck
position += normalMargin.Normalized * collisionMargin;
//Console.Print("pushin");
if (plane == hitNormals.Count)
{
@@ -537,12 +636,15 @@ namespace Game
// categorize position
onGround = true;
Vector3 groundDelta = Physics.Gravity.Normalized * (collisionMargin * 2);
Vector3 groundDelta = Physics.Gravity.Normalized;//Physics.Gravity.Normalized * (collisionMargin * 2);
//if (velocity.Y < 0f)
// groundDelta = Physics.Gravity.Normalized * velocity.Y * Time.DeltaTime;
TraceInfo traceGround = TracePlayer(position, position + groundDelta);
if (!traceGround.startSolid && traceGround.fraction < 1f &&
-Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal) < slopeNormal)
{
//Console.Print("slope?");
// slope
// clip velocity
Vector3 bounce = groundDelta;
@@ -567,6 +669,7 @@ namespace Game
else
{
onGround = !traceGround.startSolid;
//Console.Print("issolid? :" + traceGround.startSolid);
}
// TODO: snap to ground here