Created
September 24, 2021 14:56
-
-
Save HassakuTb/8f31310674f32b8882fe61d24d5b27fd to your computer and use it in GitHub Desktop.
Move box with collider but without rigidbody in Unity
This file contains hidden or 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
using UnityEngine; | |
namespace HassakuLab.Physics2D.BoxSystem | |
{ | |
/** | |
* Rigidbody for BoxSystem | |
*/ | |
[RequireComponent(typeof(Rigidbody2D))] | |
[RequireComponent(typeof(BoxCollider2D))] | |
public class DynamicBox : MonoBehaviour | |
{ | |
private Rigidbody2D _rigidbody; | |
private BoxCollider2D _collider; | |
private const float ShrinkFactor = 0.996f; | |
[SerializeField] private LayerMask hitMask; | |
[SerializeField] private Vector2 velocity; | |
private readonly RaycastHit2D[] hitBuffer = new RaycastHit2D[1]; | |
private void Awake() | |
{ | |
_rigidbody = GetComponent<Rigidbody2D>(); | |
_collider = GetComponent<BoxCollider2D>(); | |
} | |
/// <summary> | |
/// velocity of object | |
/// </summary> | |
public Vector2 Velocity | |
{ | |
get => velocity; | |
set => velocity = value; | |
} | |
/// <summary> | |
/// 壁摺りベクトルの計算 | |
/// </summary> | |
/// <param name="forward">壁に衝突した後の進行方向ベクトル</param> | |
/// <param name="normal">衝突面の法線ベクトル</param> | |
/// <returns>壁摺りベクトル</returns> | |
private static Vector2 CalculateScratchVector(Vector2 forward, Vector2 normal) | |
{ | |
return forward - Vector2.Dot(forward, normal) * normal; | |
} | |
/// <summary> | |
/// 壁摺りを考慮した移動ベクトルを計算する | |
/// </summary> | |
/// <param name="origin">BoxCast開始の中心地点</param> | |
/// <param name="velocityDelta">壁摺りを考慮しない移動ベクトル</param> | |
/// <returns></returns> | |
private Vector2 CalculateActualTranslation(Vector2 origin, Vector2 velocityDelta) | |
{ | |
if (Mathf.Abs(velocityDelta.x) < 0.01f) velocityDelta.x = 0; | |
if (Mathf.Abs(velocityDelta.y) < 0.01f) velocityDelta.y = 0; | |
if(velocityDelta.sqrMagnitude < 0.0001f) return Vector2.zero; | |
int hitCount = UnityEngine.Physics2D.BoxCastNonAlloc( | |
origin: origin, | |
size: _collider.size, | |
angle: 0f, | |
direction: velocityDelta.normalized, | |
results: hitBuffer, | |
distance: velocityDelta.magnitude, | |
layerMask: hitMask | |
); | |
// Hitしない場合はそのまま結果 | |
if (hitCount == 0) return velocityDelta; | |
// Hitする場合は壁摺りと合成する | |
RaycastHit2D hit = hitBuffer[0]; | |
Vector2 direct = velocityDelta.normalized * (hit.distance * ShrinkFactor); // avoid collision perfectly | |
Vector2 scratch = CalculateScratchVector(velocityDelta - direct, hit.normal); | |
return direct + CalculateActualTranslation(origin + direct, scratch); | |
} | |
/// <summary> | |
/// 移動ベクトル分だけオブジェクトの移動を試みる | |
/// </summary> | |
/// <param name="velocityDelta">移動ベクトル</param> | |
private void TranslateObject(Vector2 velocityDelta) | |
{ | |
Vector2 origin = (Vector2)transform.position + _collider.offset; | |
transform.Translate(CalculateActualTranslation(origin, velocityDelta)); | |
} | |
private void SimulateStep(float deltaTime) | |
{ | |
TranslateObject(Velocity * deltaTime); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment