moar shit
This commit is contained in:
@@ -1,73 +1,114 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CharacterEngine.Primitives
|
||||
{
|
||||
public sealed class CECollider
|
||||
public class CECollider
|
||||
{
|
||||
public static int[,] edges = new int[,]
|
||||
{
|
||||
{0, 4}, {0, 2}, {0, 6},
|
||||
{1, 7}, {1, 5}, {1, 3},
|
||||
{3, 4}, {3, 2}, {6, 5},
|
||||
{6, 7}, {7, 2}, {5, 4}
|
||||
{0, 2}, {0, 3}, {1, 2},{1, 3}
|
||||
};
|
||||
|
||||
public static int[,] faces = new int[,]
|
||||
{
|
||||
{0, 3}, {0, 5}, {0, 7},
|
||||
{1, 6}, {1, 4}, {1, 2}
|
||||
};
|
||||
|
||||
private Collider collider;
|
||||
public Collider Coll
|
||||
|
||||
private BoxCollider2D collider;
|
||||
public BoxCollider2D Coll
|
||||
{
|
||||
get { return collider; }
|
||||
}
|
||||
|
||||
public Vector3 position
|
||||
public virtual Vector2 position
|
||||
{
|
||||
get { return collider.bounds.center; }
|
||||
}
|
||||
|
||||
public readonly Vector3[] localPoints;
|
||||
public float Height
|
||||
{
|
||||
get { return (GetPoint(0) - GetPoint(3)).magnitude; }
|
||||
}
|
||||
public float Width
|
||||
{
|
||||
get { return (GetPoint(0) - GetPoint(2)).magnitude; }
|
||||
}
|
||||
|
||||
public CECollider (Collider coll)
|
||||
public Vector2 Max
|
||||
{
|
||||
get { return GetPoint(0); }
|
||||
}
|
||||
public Vector2 Min
|
||||
{
|
||||
get { return GetPoint(1); }
|
||||
}
|
||||
|
||||
public Vector2 AABBMax
|
||||
{
|
||||
get { return GetAABBPoint(0); }
|
||||
}
|
||||
public Vector2 AABBMin
|
||||
{
|
||||
get { return GetAABBPoint(1); }
|
||||
}
|
||||
|
||||
public readonly Vector2[] localPoints;
|
||||
|
||||
public CECollider (BoxCollider2D coll)
|
||||
{
|
||||
collider = coll;
|
||||
|
||||
///COLLIDER CONSTANT RELATIVE POINTS
|
||||
localPoints = new Vector3[]
|
||||
localPoints = new Vector2[]
|
||||
{
|
||||
coll.bounds.size * 0.5f, //max
|
||||
-coll.bounds.size * 0.5f, //min
|
||||
new Vector3(-coll.bounds.extents.x, coll.bounds.extents.y, coll.bounds.extents.z),
|
||||
new Vector3(-coll.bounds.extents.x, coll.bounds.extents.y, -coll.bounds.extents.z),
|
||||
new Vector3(coll.bounds.extents.x, coll.bounds.extents.y, -coll.bounds.extents.z),
|
||||
new Vector3(coll.bounds.extents.x, -coll.bounds.extents.y, -coll.bounds.extents.z),
|
||||
new Vector3(coll.bounds.extents.x, -coll.bounds.extents.y, coll.bounds.extents.z),
|
||||
new Vector3(-coll.bounds.extents.x, -coll.bounds.extents.y, coll.bounds.extents.z)
|
||||
coll.size * 0.5f, //max
|
||||
-coll.size * 0.5f, //min
|
||||
new Vector2(-coll.size.x * 0.5f, coll.size.y * 0.5f),
|
||||
new Vector2(coll.size.x * 0.5f, -coll.size.y * 0.5f)
|
||||
};
|
||||
}
|
||||
|
||||
public Vector3 GetPoint (int index)
|
||||
/// <summary>
|
||||
/// GET REAL WORLD POINT OF COLLIDER
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
public virtual Vector2 GetPoint (int index)
|
||||
{
|
||||
return position + localPoints[index];
|
||||
return position + (Vector2)(collider.transform.rotation * Vector2.Scale(localPoints[index], collider.transform.lossyScale));
|
||||
}
|
||||
public virtual Vector2 GetPoint(int index, Vector2 position)
|
||||
{
|
||||
return position + (Vector2)(collider.transform.rotation * Vector2.Scale(localPoints[index], collider.transform.lossyScale));
|
||||
}
|
||||
public virtual Vector2 GetAABBPoint(int index)
|
||||
{
|
||||
return position + (Vector2)(Vector2.Scale(localPoints[index], collider.transform.lossyScale));
|
||||
}
|
||||
public virtual Vector2 GetAABBPoint(int index, Vector2 position)
|
||||
{
|
||||
return position + (Vector2)(Vector2.Scale(localPoints[index], collider.transform.lossyScale));
|
||||
}
|
||||
|
||||
public bool ContainsPoint (Vector2 p)
|
||||
{
|
||||
p = position + (Vector2)(Quaternion.Inverse(collider.transform.rotation) * (p - position));
|
||||
bool insideX = p.x > AABBMin.x && p.x < AABBMax.x;
|
||||
bool insideY = p.y > AABBMin.y && p.y < AABBMax.y;
|
||||
|
||||
return insideX && insideY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Collision test along a path
|
||||
/// </summary>
|
||||
public RaycastHit SweepTest(Vector3 dir, float distance, float skinWidth = 1.0f)
|
||||
public CECollision SweepTest(Vector2 dir, float distance)
|
||||
{
|
||||
RaycastHit hit = new RaycastHit();
|
||||
CECollision hit = new CECollision();
|
||||
|
||||
for (int i = 0; i <= CEPrimitives.sweepResolution; i++)
|
||||
{
|
||||
Vector3 currentDistance = dir.normalized * (distance * (i / CEPrimitives.sweepResolution));
|
||||
hit = BoxCast(position + currentDistance, skinWidth);
|
||||
Vector2 currentDistance = dir.normalized * (distance * (i / CEPrimitives.sweepResolution));
|
||||
hit = BoxCast(position + currentDistance);
|
||||
|
||||
if (hit.distance != 0.0f) break;
|
||||
if (hit.impulse.magnitude != 0.0f) break;
|
||||
}
|
||||
|
||||
return hit;
|
||||
@@ -76,45 +117,51 @@ namespace CharacterEngine.Primitives
|
||||
/// <summary>
|
||||
/// Collision test in an specific point
|
||||
/// </summary>
|
||||
public RaycastHit BoxCast(Vector3 position, float skinWidth = 1.0f)
|
||||
public CECollision BoxCast(Vector2 position)
|
||||
{
|
||||
int mask = LayerMask.GetMask("Default");
|
||||
|
||||
RaycastHit outHit = new RaycastHit();
|
||||
CECollision collision = new CECollision();
|
||||
RaycastHit2D outHit = new RaycastHit2D();
|
||||
|
||||
|
||||
///FACE CAST
|
||||
for (int i = 0; i < faces.GetLength(0); i++)
|
||||
for (int i = 0; i < edges.GetLength(0); i++)
|
||||
{
|
||||
//Debug.DrawLine(points[faces[i, 0]], points[faces[i, 1]], Color.blue);
|
||||
outHit = Physics2D.Linecast(GetPoint(edges[i, 0], position), GetPoint(edges[i, 1], position), mask);
|
||||
|
||||
if (!Physics.Linecast(position + localPoints[faces[i, 0]] * skinWidth, position + localPoints[faces[i, 1]] * skinWidth, out outHit, mask, QueryTriggerInteraction.Ignore))
|
||||
if (!outHit)
|
||||
{
|
||||
continue;
|
||||
outHit = Physics2D.Linecast(GetPoint(edges[i, 1], position), GetPoint(edges[i, 0], position), mask);
|
||||
}
|
||||
|
||||
///RETURN DISTANCE FROM CENTER
|
||||
return outHit;
|
||||
if (outHit) break;
|
||||
}
|
||||
|
||||
///EDGE CAST
|
||||
for (int i = 0; i < CECollider.edges.GetLength(0); i++)
|
||||
if (outHit)
|
||||
{
|
||||
//Debug.DrawLine(points[edges[i, 0]], points[edges[i, 1]], Color.red);
|
||||
|
||||
if (!Physics.Linecast(position + localPoints[edges[i, 0]] * skinWidth, position + localPoints[edges[i, 1]] * skinWidth, out outHit, mask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
if (!Physics.Linecast(position + localPoints[edges[i, 1]] * skinWidth, position + localPoints[edges[i, 0]] * skinWidth, out outHit, mask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
///RETURN DISTANCE FROM CENTER
|
||||
return outHit;
|
||||
CECollider agent = new CECollider((BoxCollider2D)outHit.collider);
|
||||
CECollider myAgent = new CEVirtualCollider(position, collider);
|
||||
collision = CECollision.ResolveCollision(myAgent, agent);
|
||||
}
|
||||
|
||||
///IF REACH HERE DIDNT FOUND SHIT
|
||||
return outHit;
|
||||
return collision;
|
||||
}
|
||||
}
|
||||
|
||||
public class CEVirtualCollider : CECollider
|
||||
{
|
||||
protected Vector2 virtualPosition;
|
||||
public override Vector2 position
|
||||
{
|
||||
get
|
||||
{
|
||||
return virtualPosition;
|
||||
}
|
||||
}
|
||||
|
||||
public CEVirtualCollider (Vector2 pos, BoxCollider2D coll) : base(coll)
|
||||
{
|
||||
virtualPosition = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace CharacterEngine.Primitives
|
||||
{
|
||||
public struct CECollision
|
||||
{
|
||||
public Vector2 impulse;
|
||||
public Vector2 point;
|
||||
public Vector2 normal;
|
||||
|
||||
/// <summary>
|
||||
/// RESOLVE THE COLLISION AND RETURN A COLLISION VALUE
|
||||
/// a = Collider wich is dynamic
|
||||
/// b = static Collider
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
public static CECollision ResolveCollision (CECollider a, CECollider b)
|
||||
{
|
||||
Vector2 closestPoint = Vector2.zero;
|
||||
CECollision collision = new CECollision();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vector2 currentPoint = a.GetPoint(i);
|
||||
if (b.ContainsPoint(currentPoint))
|
||||
{
|
||||
closestPoint = ClosestPointInBounds(b, currentPoint);
|
||||
|
||||
collision.impulse = closestPoint - currentPoint;
|
||||
collision.normal = collision.impulse.normalized;
|
||||
collision.point = closestPoint;
|
||||
|
||||
return collision;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vector2 currentPoint = b.GetPoint(i);
|
||||
if (a.ContainsPoint(currentPoint))
|
||||
{
|
||||
closestPoint = ClosestPointInBounds(a, currentPoint);
|
||||
|
||||
collision.impulse = (closestPoint - currentPoint) * -1;
|
||||
collision.normal = collision.impulse.normalized;
|
||||
collision.point = closestPoint;
|
||||
|
||||
return collision;
|
||||
}
|
||||
}
|
||||
|
||||
//IF REACH HERE DIDNT RESOLVE SHIT
|
||||
Debug.Log("Could not resolve collision");
|
||||
return collision;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GET CLOSEST CONTACT POINT
|
||||
/// </summary>
|
||||
/// <param name="coll"></param>
|
||||
/// <param name="point"></param>
|
||||
/// <returns></returns>
|
||||
public static Vector2 ClosestPointInBounds (CECollider coll, Vector2 point)
|
||||
{
|
||||
Vector2 smallerDelta = Vector2.zero;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Vector2 cpis = ClosestVectorToSegment(point, coll.GetPoint(CECollider.edges[i, 0]), coll.GetPoint(CECollider.edges[i, 1]));
|
||||
Vector2 delta = cpis - point;
|
||||
|
||||
if (smallerDelta == Vector2.zero) smallerDelta = delta;
|
||||
else
|
||||
{
|
||||
if (delta.sqrMagnitude < smallerDelta.sqrMagnitude)
|
||||
smallerDelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
return point + smallerDelta;
|
||||
}
|
||||
|
||||
public static Vector2 ClosestVectorToSegment (Vector2 p, Vector2 a, Vector2 b)
|
||||
{
|
||||
Vector2 segmentNormal = Vector3.Cross((a- b).normalized, Vector3.forward);
|
||||
Vector2 distanceToPointA = a - p;
|
||||
Vector2 distanceToPointB = b - p;
|
||||
|
||||
return p + (Vector2)Vector3.Project(distanceToPointA, segmentNormal);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 348109b22797c724282c6d7807b00b73
|
||||
timeCreated: 1463330859
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -24,8 +24,8 @@ namespace CharacterEngine.Primitives
|
||||
private CEController controller;
|
||||
public readonly CECollider collider;
|
||||
|
||||
private Vector3 velocity;
|
||||
public Vector3 Velocity
|
||||
private Vector2 velocity;
|
||||
public Vector2 Velocity
|
||||
{
|
||||
get { return velocity; }
|
||||
}
|
||||
@@ -42,7 +42,7 @@ namespace CharacterEngine.Primitives
|
||||
public CEPrimitives (CEController controller)
|
||||
{
|
||||
this.controller = controller;
|
||||
collider = new CECollider(controller.GetComponent<Collider>());
|
||||
collider = new CECollider(controller.GetComponent<BoxCollider2D>());
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -89,20 +89,22 @@ namespace CharacterEngine.Primitives
|
||||
|
||||
bool CollideAndSlide()
|
||||
{
|
||||
Vector3 oldPos = transform.position;
|
||||
Vector3 predictedPos = oldPos + velocity * Time.fixedDeltaTime;
|
||||
Vector3 correctedPos = predictedPos;
|
||||
|
||||
RaycastHit hit = collider.SweepTest(velocity, velocity.magnitude * Time.fixedDeltaTime, controller.skinWidth);
|
||||
Vector2 oldPos = transform.position;
|
||||
Vector2 predictedPos = oldPos + velocity * Time.fixedDeltaTime;
|
||||
Vector2 correctedPos = predictedPos;
|
||||
|
||||
if (hit.collider == null) { return false; }
|
||||
CECollision hit = collider.SweepTest(velocity, velocity.magnitude * Time.fixedDeltaTime);
|
||||
|
||||
Vector3 obstacleHitPoint = hit.point;
|
||||
Vector3 obstacleNormal = hit.normal;
|
||||
Vector3 obstacleTangent = Vector3.Cross(obstacleNormal, Vector3.forward);
|
||||
if (hit.normal == Vector2.zero) { return false; }
|
||||
|
||||
Vector2 obstacleHitPoint = hit.point;
|
||||
Vector2 obstacleNormal = hit.normal;
|
||||
Vector2 obstacleTangent = Vector3.Cross(obstacleNormal, Vector3.forward);
|
||||
if (obstacleTangent.magnitude == 0)
|
||||
obstacleTangent = Vector3.Cross(obstacleNormal, Vector3.up);
|
||||
|
||||
Debug.DrawRay(hit.point, hit.normal);
|
||||
/*
|
||||
Plane obstaclePlane = new Plane(obstacleNormal, obstacleHitPoint);
|
||||
Ray velRay = new Ray(oldPos, velocity);
|
||||
@@ -112,12 +114,11 @@ namespace CharacterEngine.Primitives
|
||||
Vector3 vectorFromCenter = obstacleHitPoint - Coll.bounds.center ;
|
||||
*/
|
||||
|
||||
correctedPos = oldPos + velocity.normalized * hit.distance;
|
||||
|
||||
/*
|
||||
GameObject a = Instantiate(this.gameObject, correctedPos, transform.rotation) as GameObject;
|
||||
a.GetComponent<EntityController>().enabled = false;
|
||||
*/
|
||||
correctedPos = predictedPos + hit.impulse;
|
||||
|
||||
//GameObject a = CEController.Instantiate(controller.gameObject, correctedPos, transform.rotation) as GameObject;
|
||||
//a.GetComponent<CEController>().enabled = false;
|
||||
|
||||
|
||||
Vector3 epsilon = correctedPos - predictedPos;
|
||||
|
||||
@@ -129,9 +130,7 @@ namespace CharacterEngine.Primitives
|
||||
*/
|
||||
|
||||
Vector3 projectedForce = Vector3.Project(velocity, obstacleTangent);
|
||||
|
||||
velocity = projectedForce;
|
||||
velocity.z = 0.0f;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -143,7 +142,7 @@ namespace CharacterEngine.Primitives
|
||||
|
||||
void Move()
|
||||
{
|
||||
transform.position += velocity * Time.deltaTime;
|
||||
transform.position += (Vector3)velocity * Time.deltaTime;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
22
New Unity Project/Assets/Scripts/CharacterController/test.cs
Normal file
22
New Unity Project/Assets/Scripts/CharacterController/test.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using CharacterEngine.Primitives;
|
||||
|
||||
public class test : MonoBehaviour {
|
||||
|
||||
public BoxCollider2D coll;
|
||||
protected CECollider ce;
|
||||
// Use this for initialization
|
||||
void Start () {
|
||||
ce = new CECollider(coll);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update () {
|
||||
if (ce.ContainsPoint(transform.position))
|
||||
{
|
||||
Vector2 p = CECollision.ClosestPointInBounds(ce, transform.position);
|
||||
Debug.DrawLine(p, transform.position, Color.red);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0ed370640e457f4ca5447af56a3319c
|
||||
timeCreated: 1463341313
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user