using System.Collections; using System.Collections.Generic; using UnityEngine; public enum PrimitiveType { None, Ball, Box } /// /// 物理碰撞体基类 /// 对于格斗游戏来说只需要Box和Ball两种 /// public abstract class PhysicsPrimitive : MonoBehaviour { public virtual PrimitiveType Type { get { return PrimitiveType.None; } } /// /// 世界坐标,物理模拟是在世界空间,本地坐标没有意义 /// public Vector3 Position { get { Vector3 euler = Quaternion.ToEulerAngles(transform.rotation); euler.y = Mathf.Rad2Deg * euler.y; Vector3 res = m_Center; res.x = (euler.y > 0 && euler.y <= 180) ? -res.x : res.x; res = transform.position + res; return res; } } [SerializeField] /// /// 这个primitive是否参与物理计算,用来快速给物体取消和恢复重力影响 /// protected bool m_IsActive; public bool IsActive { get { return m_IsActive; } } /// /// 唯一ID /// protected int m_ID; public int ID { get { return m_ID; } } [Tooltip("给primitive分组,决定大组和大组之间是否有碰撞检测")] [SerializeField] protected PhysicsGroup m_Group; public PhysicsGroup Group { get { return m_Group; } } [Tooltip("给primitive一个标记,表明它的从属关系。帮助做hitbox和hurtbox")] [SerializeField] protected PhysicsTag m_Tag; public PhysicsTag Tag { get { return m_Tag; } } [Tooltip("同一个标签的没有碰撞检测")] [SerializeField] protected string m_Label; public string Label { get { return m_Label; } } [Tooltip("单个碰撞体的描述(名称),作为标识用来识别")] [SerializeField] protected string m_Title; public string Title { get { return m_Title; } } [SerializeField] protected string m_Desc; public string Desc { get { return m_Desc; } } /// /// 初始化,设置一些公共数据 /// protected void OnInit() { m_ID = UIDManager.Acquire(); PhysicsWorld.Instance.AddPrimitive(this); } protected Color Color_Green = new Color(0, 1, 0, 0.5f); [SerializeField] protected Color m_HintColor = new Color(0, 0, 0, 0.5f); [Tooltip("Physics body, leave blank and primitive will be static.")] [SerializeField] protected PhysicsBody m_Body; public PhysicsBody Body { get { return m_Body; } } /// /// 中心点在本地空间的位置 /// public Vector3 m_Center; /// /// 边界:左、右、上、下 /// public Vector4 Bound { get { Vector4 bound = new Vector4(); if(this is PhysicsBox) { PhysicsBox box = this as PhysicsBox; bound.x = box.Left; bound.y = box.Right; bound.z = box.Top; bound.w = box.Bottom; } else if(this is PhysicsBall) { PhysicsBall ball = this as PhysicsBall; bound.x = ball.Position.x - ball.Radius; bound.y = ball.Position.x + ball.Radius; bound.z = ball.Position.y + ball.Radius; bound.w = ball.Position.y - ball.Radius; } return bound; } } public bool IsOnGround { get { if (Mathf.Approximately(Bound.w, PhysicsWorld.Ground)) return true; return Bound.w <= PhysicsWorld.Ground; } } public bool IsInAir { get { //return Bound.w > PhysicsWorld.Ground; return !IsOnGround; } } }