using System.Collections; using UnityEngine; namespace Lightbug.Utilities { /// /// An implementation of RigidbodyComponent for 2D rigidbodies. /// 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(); _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"); } }