Skip to content

Instantly share code, notes, and snippets.

@HassakuTb
Created September 24, 2021 14:56
Show Gist options
  • Save HassakuTb/8f31310674f32b8882fe61d24d5b27fd to your computer and use it in GitHub Desktop.
Save HassakuTb/8f31310674f32b8882fe61d24d5b27fd to your computer and use it in GitHub Desktop.
Move box with collider but without rigidbody in Unity
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