using System; using System.Collections; using System.Collections.Generic; using System.Net.Configuration; using BITFALL.Scene; using Unity.Mathematics; using UnityEngine; using UnityEngine.AI; namespace BITKit { public class PhysicsDoor : MonoBehaviour, IAction, IDescription, ISceneBlockArea { public enum State { Close, Open, HalfOpen, Locked, } [SerializeField] private string description; [SerializeField] private bool allowPhysics = true; [SerializeField] private Rigidbody root; [SerializeField] private new Collider collider; [SerializeField] private NavMeshObstacle obstacle; [SerializeField] private Vector3 openEuler; [SerializeField] private Vector3 closeEuler; [SerializeField] private State state; [SerializeField] private Collider[] ignoreColliders; [SerializeReference, SubclassSelector] private IReference envName; private Vector3 _initialPosition; private void Start() { var selfColliders = GetComponentsInChildren(true); var parentCollider = GetComponentInParent(true); foreach (var self in selfColliders) { foreach (var ignore in ignoreColliders) { Physics.IgnoreCollision(self, ignore, true); } if (parentCollider is not null) Physics.IgnoreCollision(self, parentCollider, true); } _initialPosition = root.transform.localPosition; UpdateState(); } public void Execute() { switch (state) { case State.Open: state = State.Close; UpdateState(); break; case State.Close: state = State.Open; UpdateState(); break; } } public void UpdateState(bool isClosed) { state = isClosed ? State.Close : State.Open; //root.transform.localPosition = _initialPosition; root.transform.localEulerAngles = isClosed ? closeEuler : openEuler; if (allowPhysics) root.isKinematic = isClosed; if (envName is not null) { Data.Set(envName.Value, isClosed); } } private void UpdateState() { switch (state) { case State.Close: case State.Open: var isClosed = state switch { State.Locked => true, State.Close => true, State.Open => false, _ => true }; UpdateState(isClosed); if (obstacle) { obstacle.enabled = isClosed; } break; } } public string Name => state is State.Locked ? "锁住了" : description; public bool IsBlocked => state is not State.Open; public bool InRange(float3 position) { return collider.bounds.Contains(position); } public bool InRange(float3 position, float3 direction) { if (direction is { x: 0, y: 0, z: 0 }) return false; var ray = new Ray(position, ((Vector3)direction).normalized); if (collider.Raycast(ray, out var hit, 1)) { Debug.DrawLine(position, hit.point, Color.red, 1); return true; } Debug.DrawLine(position, position + direction, Color.blue, 1); return false; } } }