Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from yuzhengwen/Testing
Initial commit
- Loading branch information
Showing
122 changed files
with
18,031 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"version": "1.0", | ||
"components": [ | ||
"Microsoft.VisualStudio.Workload.ManagedGame" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
using static PlayerPhysics; | ||
|
||
public class Movement : MonoBehaviour | ||
{ | ||
[Header("Jump Parameters")] | ||
public float jumpHeight = 4f; | ||
public float timeToApex = .5f; | ||
|
||
// will be set based on jump height & time to apex | ||
float jumpVel; | ||
float jumpGravity; | ||
float jumpGravityModifier; | ||
|
||
float moveSpeed = 6; | ||
float gravity = -10; | ||
|
||
Vector2 targetVel; | ||
|
||
float xVelSmooth; | ||
[Header("Smoothing")] | ||
public float smoothTimeGrounded = .05f; | ||
public float smoothTimeAirborne = .15f; | ||
|
||
PlayerPhysics phyObj; | ||
|
||
void Start() | ||
{ | ||
phyObj = GetComponent<PlayerPhysics>(); | ||
|
||
jumpGravity = -2 * (jumpHeight / Mathf.Pow(timeToApex, 2)); | ||
jumpGravityModifier = jumpGravity / gravity; | ||
jumpVel = -(jumpGravity * timeToApex); | ||
} | ||
|
||
void Update() | ||
{ | ||
if (phyObj.collisionInfo.below || phyObj.collisionInfo.above) targetVel.y = 0; | ||
|
||
Vector2 input = new Vector2(Input.GetAxisRaw("Horizontal"), 0); | ||
|
||
if (Input.GetKeyDown(KeyCode.Space) && phyObj.collisionInfo.below) | ||
{ | ||
targetVel.y = jumpVel; | ||
} | ||
float rawTargetXVel = input.x * moveSpeed; | ||
targetVel.x = Mathf.SmoothDamp(targetVel.x, rawTargetXVel, ref xVelSmooth, phyObj.collisionInfo.below ? smoothTimeGrounded : smoothTimeAirborne); | ||
targetVel.y += jumpGravity * Time.deltaTime; | ||
phyObj.Move(targetVel * Time.deltaTime); | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
|
||
public class PhysicsObject : MonoBehaviour | ||
{ | ||
public float gravityModifier = 1f; | ||
protected Vector2 velocity; | ||
protected const float minMoveDistance = 0.001f; | ||
|
||
protected ContactFilter2D contactFilter; | ||
protected List<RaycastHit2D> hits = new(); | ||
protected const float shellRadius = 0.01f; // slight padding between objects (when colliding) | ||
public const float minGroundNormalY = 0.707f; // value of y for a unit vector at 45 deg from (0,1) | ||
protected Vector2 groundNormal = new(0, 1); | ||
protected Vector2 groundParallel; | ||
protected bool grounded = false; | ||
|
||
protected Vector2 targetVelocity; | ||
|
||
protected Rigidbody2D rb; | ||
|
||
private void Awake() | ||
{ | ||
rb = GetComponent<Rigidbody2D>(); | ||
} | ||
// Start is called before the first frame update | ||
void Start() | ||
{ | ||
contactFilter.useTriggers = false; // dont collide with triggers | ||
contactFilter.SetLayerMask(Physics2D.GetLayerCollisionMask(gameObject.layer)); // only collide with layers that can collide with layer of gameobject (in physics2d settings) | ||
contactFilter.useLayerMask = true; | ||
} | ||
// we will separately check collisions | ||
// y will check for ground, if slope detected, treat as flat ground | ||
// x will check for wall/ slope | ||
private void FixedUpdate() | ||
{ | ||
velocity += gravityModifier * Time.deltaTime * Physics2D.gravity; // dv = g * dt | ||
velocity.x = targetVelocity.x; | ||
grounded = false; | ||
// initial distance we want to move (without accounting for collisions) | ||
Vector2 deltaPos = velocity * Time.deltaTime; // dx = v * dt | ||
|
||
groundParallel = new(groundNormal.y, -groundNormal.x); // gets a vector perpendicular to ground normal | ||
Debug.DrawRay(transform.position, groundParallel * 2, Color.red); | ||
|
||
Vector2 move = deltaPos.y * Vector2.up; | ||
Vector2 y = Movement(move, true); | ||
|
||
move = groundParallel * deltaPos.x; //move along slope/flat ground at same speed | ||
Vector2 x = Movement(move, false); | ||
|
||
rb.MovePosition(rb.position + (x + y)); | ||
Debug.DrawRay(transform.position, groundNormal, Color.green); | ||
Debug.DrawRay(transform.position, (x + y) * 10, Color.black); | ||
} | ||
private Vector2 Movement(Vector2 move, bool yMovement) | ||
{ | ||
float distance = move.magnitude; // distance we want to move | ||
if (distance > minMoveDistance) | ||
{ | ||
// one problem right now is that it returns 1 raycasthit per collider, very buggy when transitioning from flat to slope | ||
int count = rb.Cast(move, contactFilter, hits, distance + shellRadius); | ||
Debug.Log($"Colliding with {count} objects"); | ||
foreach (RaycastHit2D hit in hits) | ||
{ | ||
Vector2 normal = hit.normal; | ||
Debug.DrawRay(hit.point, normal, Color.blue); | ||
if (IsGround(normal)) | ||
{ | ||
grounded = true; | ||
groundNormal = normal; | ||
if (yMovement) | ||
{ | ||
normal.x = 0; // if we are considered grounded, set normal to (0, 1) | ||
} | ||
} | ||
if (IsWall(normal)) | ||
{ | ||
if (velocity.x * normal.x > 0) velocity.x = 0; | ||
} | ||
else | ||
{ | ||
float projection = Vector2.Dot(velocity, normal); | ||
if (projection < 0) | ||
{ | ||
velocity -= projection * normal; // cancel out component of velocity parallel to normal | ||
} | ||
} | ||
float modifiedDistance = hit.distance - shellRadius; // distance between object and incoming colliding obj | ||
distance = modifiedDistance < distance ? modifiedDistance : distance; | ||
} | ||
} | ||
return (move.normalized * distance); | ||
} | ||
// if slope <= 45 deg considered ground | ||
private bool IsGround(Vector2 normal) | ||
{ | ||
return normal.y >= minGroundNormalY; | ||
} | ||
// if 45 deg < slope < 90 deg considered wall | ||
private bool IsWall(Vector2 normal) | ||
{ | ||
return normal.y >= 0 && normal.y < minGroundNormalY; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using UnityEngine; | ||
|
||
public class PlayerPhysics : MonoBehaviour | ||
{ | ||
public LayerMask collisionMask; | ||
|
||
const float skinWidth = .015f; | ||
public int horizontalRayCount = 4; | ||
public int verticalRayCount = 4; | ||
|
||
float horizontalRaySpacing; | ||
float verticalRaySpacing; | ||
|
||
BoxCollider2D col; | ||
Corners raycastOrigins; | ||
public CollisionInfo collisionInfo; | ||
|
||
void Start() | ||
{ | ||
col = GetComponent<BoxCollider2D>(); | ||
CalculateRaySpacing(); | ||
} | ||
|
||
public void Move(Vector3 deltaPos) | ||
{ | ||
collisionInfo.Reset(); | ||
UpdateRaycastOrigins(); | ||
if (deltaPos.x != 0) // if not moving in x axis, no need to check hor collisions | ||
{ | ||
HorizontalCollisions(ref deltaPos); | ||
} | ||
if (deltaPos.y != 0) // same, but since gravity is always applied, this will always !=0 | ||
{ | ||
VerticalCollisions(ref deltaPos); | ||
} | ||
Debug.DrawRay(transform.position, deltaPos * (1/Time.deltaTime)/2, Color.red); | ||
transform.Translate(deltaPos); | ||
} | ||
|
||
void HorizontalCollisions(ref Vector3 deltaPos) | ||
{ | ||
float xDir = Mathf.Sign(deltaPos.x); | ||
float rayLength = Mathf.Abs(deltaPos.x) + skinWidth; | ||
|
||
for (int i = 0; i < horizontalRayCount; i++) | ||
{ | ||
Vector2 rayOrigin = (xDir == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight; | ||
rayOrigin += Vector2.up * (horizontalRaySpacing * i); | ||
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * xDir, rayLength, collisionMask); | ||
Debug.DrawRay(rayOrigin, Vector2.right * xDir * rayLength, Color.red); | ||
|
||
if (hit) | ||
{ | ||
deltaPos.x = (hit.distance - skinWidth) * xDir; | ||
rayLength = hit.distance; | ||
|
||
collisionInfo.left = xDir == -1; | ||
collisionInfo.right = xDir == 1; | ||
} | ||
} | ||
} | ||
|
||
void VerticalCollisions(ref Vector3 deltaPos) | ||
{ | ||
float yDir = Mathf.Sign(deltaPos.y); | ||
float rayLength = Mathf.Abs(deltaPos.y) + skinWidth; | ||
|
||
for (int i = 0; i < verticalRayCount; i++) | ||
{ | ||
Vector2 rayOrigin = (yDir == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft; | ||
rayOrigin += Vector2.right * (verticalRaySpacing * i + deltaPos.x); | ||
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * yDir, rayLength, collisionMask); | ||
|
||
Debug.DrawRay(rayOrigin, Vector2.up * yDir * rayLength, Color.red); | ||
|
||
if (hit) | ||
{ | ||
deltaPos.y = (hit.distance - skinWidth) * yDir; | ||
rayLength = hit.distance; | ||
|
||
collisionInfo.below = yDir == -1; | ||
collisionInfo.above = yDir == 1; | ||
} | ||
} | ||
} | ||
|
||
void UpdateRaycastOrigins() | ||
{ | ||
Bounds bounds = col.bounds; | ||
bounds.Expand(skinWidth * -2); | ||
|
||
raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y); | ||
raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y); | ||
raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y); | ||
raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y); | ||
} | ||
|
||
void CalculateRaySpacing() | ||
{ | ||
Bounds bounds = col.bounds; | ||
bounds.Expand(skinWidth * -2); | ||
|
||
horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue); | ||
verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue); | ||
|
||
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1); | ||
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1); | ||
} | ||
|
||
struct Corners | ||
{ | ||
public Vector2 topLeft, topRight; | ||
public Vector2 bottomLeft, bottomRight; | ||
} | ||
[Serializable] | ||
public struct CollisionInfo | ||
{ | ||
public bool below, above, left, right; | ||
public void Reset() | ||
{ | ||
below = false; | ||
above = false; | ||
left = false; | ||
right = false; | ||
} | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.