222 lines
7.8 KiB
C#

using System.Collections;
using UnityEngine;
namespace Lightbug.Utilities
{
/// <summary>
/// An implementation of RigidbodyComponent for 2D rigidbodies.
/// </summary>
public sealed class RigidbodyComponent2D : RigidbodyComponent
{
Rigidbody2D _rigidbody = null;
RaycastHit2D[] _sweepBuffer = new RaycastHit2D[10];
protected override bool IsUsingContinuousCollisionDetection => _rigidbody.collisionDetectionMode > 0;
public override HitInfo Sweep(Vector3 position, Vector3 direction, float distance)
{
var p = Position;
Position = position;
int length = _rigidbody.Cast(direction, _sweepBuffer, distance);
Position = p;
_sweepBuffer.GetClosestHit(out RaycastHit2D raycastHit, length, null);
return new HitInfo(ref raycastHit, direction);
}
protected override void Awake()
{
base.Awake();
_rigidbody = gameObject.GetOrAddComponent<Rigidbody2D>();
_rigidbody.hideFlags = HideFlags.NotEditable;
previousContinuousCollisionDetection = IsUsingContinuousCollisionDetection;
}
public override bool Is2D => true;
public override float Mass
{
get => _rigidbody.mass;
set => _rigidbody.mass = value;
}
public override float LinearDrag
{
#if UNITY_6000_0_OR_NEWER
get => _rigidbody.linearDamping;
set => _rigidbody.linearDamping = value;
#else
get => _rigidbody.drag;
set => _rigidbody.drag = value;
#endif
}
public override float AngularDrag
{
#if UNITY_6000_0_OR_NEWER
get => _rigidbody.angularDamping;
set => _rigidbody.angularDamping = value;
#else
get => _rigidbody.angularDrag;
set => _rigidbody.angularDrag = value;
#endif
}
public override bool IsKinematic
{
get => _rigidbody.bodyType == RigidbodyType2D.Kinematic;
set
{
if (value == IsKinematic)
return;
// Since CCD can't be true for kinematic bodies, the body type must change to dynamic before setting CCD
if (value)
{
ContinuousCollisionDetection = false;
_rigidbody.bodyType = RigidbodyType2D.Kinematic;
}
else
{
_rigidbody.bodyType = RigidbodyType2D.Dynamic;
ContinuousCollisionDetection = previousContinuousCollisionDetection;
}
InvokeOnBodyTypeChangeEvent();
}
}
public override bool UseGravity
{
get => _rigidbody.gravityScale != 0f;
set => _rigidbody.gravityScale = value ? 1f : 0f;
}
public override bool UseInterpolation
{
get => _rigidbody.interpolation == RigidbodyInterpolation2D.Interpolate;
set => _rigidbody.interpolation = value ? RigidbodyInterpolation2D.Interpolate : RigidbodyInterpolation2D.None;
}
public override bool ContinuousCollisionDetection
{
get => _rigidbody.collisionDetectionMode == CollisionDetectionMode2D.Continuous;
set => _rigidbody.collisionDetectionMode = value ? CollisionDetectionMode2D.Continuous : CollisionDetectionMode2D.Discrete;
}
public override RigidbodyConstraints Constraints
{
get
{
switch (_rigidbody.constraints)
{
case RigidbodyConstraints2D.None:
return RigidbodyConstraints.None;
case RigidbodyConstraints2D.FreezeAll:
return RigidbodyConstraints.FreezeAll;
case RigidbodyConstraints2D.FreezePosition:
return RigidbodyConstraints.FreezePosition;
case RigidbodyConstraints2D.FreezePositionX:
return RigidbodyConstraints.FreezePositionX;
case RigidbodyConstraints2D.FreezePositionY:
return RigidbodyConstraints.FreezePositionY;
case RigidbodyConstraints2D.FreezeRotation:
return RigidbodyConstraints.FreezeRotationZ;
default:
return RigidbodyConstraints.None;
}
}
set
{
switch (value)
{
case RigidbodyConstraints.None:
_rigidbody.constraints = RigidbodyConstraints2D.None;
break;
case RigidbodyConstraints.FreezeAll:
_rigidbody.constraints = RigidbodyConstraints2D.FreezeAll;
break;
case RigidbodyConstraints.FreezePosition:
_rigidbody.constraints = RigidbodyConstraints2D.FreezePosition;
break;
case RigidbodyConstraints.FreezePositionX:
_rigidbody.constraints = RigidbodyConstraints2D.FreezePositionX;
break;
case RigidbodyConstraints.FreezePositionY:
_rigidbody.constraints = RigidbodyConstraints2D.FreezePositionY;
break;
case RigidbodyConstraints.FreezeRotation:
_rigidbody.constraints = RigidbodyConstraints2D.FreezeRotation;
break;
case RigidbodyConstraints.FreezeRotationZ:
_rigidbody.constraints = RigidbodyConstraints2D.FreezeRotation;
break;
default:
_rigidbody.constraints = RigidbodyConstraints2D.None;
break;
}
}
}
public override Vector3 Position
{
get => new Vector3(_rigidbody.position.x, _rigidbody.position.y, transform.position.z);
set => _rigidbody.position = value;
}
public override Quaternion Rotation
{
get => Quaternion.Euler(0f, 0f, _rigidbody.rotation);
set => _rigidbody.rotation = value.eulerAngles.z;
}
public override Vector3 Velocity
{
#if UNITY_6000_0_OR_NEWER
get => _rigidbody.linearVelocity;
set => _rigidbody.linearVelocity = value;
#else
get => _rigidbody.velocity;
set => _rigidbody.velocity = value;
#endif
}
public override Vector3 AngularVelocity
{
get => new Vector3(0f, 0f, _rigidbody.angularVelocity);
set => _rigidbody.angularVelocity = value.z;
}
public override void Interpolate(Vector3 position) => _rigidbody.MovePosition(position);
public override void Interpolate(Quaternion rotation) => _rigidbody.MoveRotation(rotation.eulerAngles.z);
public override Vector3 GetPointVelocity(Vector3 point) => _rigidbody.GetPointVelocity(point);
public override void AddForceToRigidbody(Vector3 force, ForceMode forceMode = ForceMode.Force)
{
ForceMode2D forceMode2D = ForceMode2D.Force;
if (forceMode == ForceMode.Impulse || forceMode == ForceMode.VelocityChange)
forceMode2D = ForceMode2D.Impulse;
_rigidbody.AddForce(force, forceMode2D);
}
public override void AddExplosionForceToRigidbody(float explosionForce, Vector3 explosionPosition, float explosionRadius, float upwardsModifier = 0)
=> Debug.LogWarning("AddExplosionForce is not available for 2D physics");
}
}