_xiaofang/xiaofang/Assets/Obi/Scripts/Common/Collisions/ObiColliderBase.cs
杨号敬 bcc74f0465 add
2024-12-18 02:18:45 +08:00

229 lines
6.0 KiB
C#

using UnityEngine;
using System;
namespace Obi
{
/**
* Implements common functionality for ObiCollider and ObiCollider2D.
*/
public abstract class ObiColliderBase : MonoBehaviour
{
[SerializeProperty("Thickness")]
[SerializeField] private float thickness = 0;
[SerializeProperty("Inverted")]
[SerializeField] private bool inverted = false;
[SerializeProperty("CollisionMaterial")]
[SerializeField] private ObiCollisionMaterial material;
[SerializeField] private int filter = ObiUtils.MakeFilter(ObiUtils.CollideWithEverything, 0);
public ObiCollisionMaterial CollisionMaterial
{
set
{
if (material != value)
{
material = value;
needsUpdate = true;
}
}
get { return material; }
}
public int Filter
{
set
{
if (filter != value)
{
filter = value;
needsUpdate = true;
}
}
get { return filter; }
}
public float Thickness
{
set
{
if (!Mathf.Approximately(thickness, value))
{
thickness = value;
needsUpdate = true;
}
}
get { return thickness; }
}
public bool Inverted
{
set
{
if (inverted != value)
{
inverted = value;
needsUpdate = true;
}
}
get { return inverted; }
}
public ObiShapeTracker Tracker
{
get { return tracker; }
}
public ObiColliderHandle Handle
{
get
{
if (shapeHandle == null)
FindSourceCollider();
return shapeHandle;
}
}
public ObiForceZone ForceZone
{
get; set;
}
public ObiRigidbodyBase Rigidbody
{
get { return obiRigidbody; }
}
protected ObiColliderHandle shapeHandle;
protected ObiRigidbodyBase obiRigidbody;
protected bool wasUnityColliderEnabled = true;
protected bool needsUpdate = true;
protected ObiShapeTracker tracker; /**< tracker object used to determine when to update the collider's shape*/
/**
* Creates an OniColliderTracker of the appropiate type.
*/
protected abstract void CreateTracker();
protected abstract Component GetUnityCollider(ref bool enabled);
protected abstract void FindSourceCollider();
protected void CreateRigidbody()
{
obiRigidbody = null;
// find the first rigidbody up our hierarchy:
Rigidbody rb = GetComponentInParent<Rigidbody>();
Rigidbody2D rb2D = GetComponentInParent<Rigidbody2D>();
// if we have an rigidbody above us, see if it has a ObiRigidbody component and add one if it doesn't:
if (rb != null)
{
obiRigidbody = rb.GetComponent<ObiRigidbody>();
if (obiRigidbody == null)
obiRigidbody = rb.gameObject.AddComponent<ObiRigidbody>();
}
else if (rb2D != null)
{
obiRigidbody = rb2D.GetComponent<ObiRigidbody2D>();
if (obiRigidbody == null)
obiRigidbody = rb2D.gameObject.AddComponent<ObiRigidbody2D>();
}
}
private void OnTransformParentChanged()
{
CreateRigidbody();
}
protected void AddCollider()
{
Component unityCollider = GetUnityCollider(ref wasUnityColliderEnabled);
if (unityCollider != null && (shapeHandle == null || !shapeHandle.isValid))
{
shapeHandle = ObiColliderWorld.GetInstance().CreateCollider();
shapeHandle.owner = this;
// Create shape tracker:
CreateTracker();
// Create rigidbody if necessary, and link ourselves to it:
CreateRigidbody();
}
}
protected void RemoveCollider()
{
ObiColliderWorld.GetInstance().DestroyCollider(shapeHandle);
// Destroy shape tracker:
if (tracker != null)
{
tracker.Destroy();
tracker = null;
}
}
public void ForceUpdate()
{
needsUpdate = true;
}
/**
* Check if the collider transform or its shape have changed any relevant property, and update their Oni counterparts.
*/
public void UpdateIfNeeded()
{
bool unityColliderEnabled = false;
Component unityCollider = GetUnityCollider(ref unityColliderEnabled);
if (unityCollider != null)
{
// Only if this object is not static:
if (tracker != null && needsUpdate)
{
tracker.UpdateIfNeeded();
}
// store isStatic, *after* updating the tracker at least once.
needsUpdate = !unityCollider.gameObject.isStatic;
}
// If the unity collider is null but its handle is valid, the unity collider has been destroyed.
else if (shapeHandle != null && shapeHandle.isValid)
RemoveCollider();
}
private void OnEnable()
{
needsUpdate = true;
// Initialize using the source collider specified by the user (or find an appropiate one).
FindSourceCollider();
}
private void OnDisable()
{
RemoveCollider();
}
}
}