From 07fd372981a16672af23e30816ade14fcb744804 Mon Sep 17 00:00:00 2001 From: chai Date: Mon, 30 Aug 2021 13:49:30 +0800 Subject: =?UTF-8?q?=E5=87=BB=E4=B8=AD=E5=8F=8D=E9=A6=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Unit/Collider/ColliderBox_Hitbox.cs | 13 ++- Assets/Scripts/Unit/Collider/CollisionSystem.cs | 110 +++++++++++++++++++-- Assets/Scripts/Unit/Component/MonsterAnimation.cs | 8 +- Assets/Scripts/Unit/Component/MonsterState.cs | 40 ++++++-- Assets/Scripts/Unit/Component/PCAnimation.cs | 2 + Assets/Scripts/Unit/Component/UnitCollider.cs | 22 +++-- .../Scripts/Unit/Controller/MonsterController.cs | 41 +++++++- Assets/Scripts/Unit/Controller/PCController.cs | 21 +++- Assets/Scripts/Unit/Controller/UnitController.cs | 16 ++- 9 files changed, 247 insertions(+), 26 deletions(-) (limited to 'Assets/Scripts/Unit') diff --git a/Assets/Scripts/Unit/Collider/ColliderBox_Hitbox.cs b/Assets/Scripts/Unit/Collider/ColliderBox_Hitbox.cs index be0749fd..2044ae7d 100644 --- a/Assets/Scripts/Unit/Collider/ColliderBox_Hitbox.cs +++ b/Assets/Scripts/Unit/Collider/ColliderBox_Hitbox.cs @@ -37,14 +37,25 @@ public partial class ColliderBox Red = 2, } + // 击中反馈 + public enum EHitResponse + { + Light = 0, + Heavy = 1, + HitAir = 2, + HitGround = 3 + } + [ColliderType(EColliderType.HitBox)] [Tooltip("允许多次击中")] public bool multiHit; + public EHitResponse hitResponse; + [Tooltip("击退距离")] public Vector3 hitBack; - + [Comment("[ 击中效果 ]", TextAnchor.MiddleCenter)] [Foldout("时间效果", 2)] diff --git a/Assets/Scripts/Unit/Collider/CollisionSystem.cs b/Assets/Scripts/Unit/Collider/CollisionSystem.cs index efbb2784..d5c96d0c 100644 --- a/Assets/Scripts/Unit/Collider/CollisionSystem.cs +++ b/Assets/Scripts/Unit/Collider/CollisionSystem.cs @@ -8,10 +8,18 @@ public struct ColliderDescriptor public UnitCollider unitCollider; } +public struct Box +{ + public Vector3 center; + public Vector3 size; +} + public struct CollisionInfo { - ColliderDescriptor collider; // 主动 - ColliderDescriptor collidee; // 从动 + public ColliderDescriptor collider; // 主动 + public ColliderDescriptor collidee; // 从动 + public Box intersection; + public bool isCollision; } public class CollisionSystem : SingletonMB @@ -77,10 +85,19 @@ public class CollisionSystem : SingletonMB for (int j = 0; j < hurtboxes.Count; ++j) { ColliderDescriptor hurtbox = hurtboxes[j]; - if (hitbox.unitCollider == hurtbox.unitCollider) // 同一个角色的hitbox和hurtbox不交互 - continue; - - } + if (hitbox.unitCollider == hurtbox.unitCollider) + continue; + if (hitbox.unitCollider.owner.type == hurtbox.unitCollider.owner.type) + continue; + CollisionInfo collision = ColliderUtility.GetCollision(hitbox, hurtbox); + if (!collision.isCollision) + continue; + if (!hitbox.unitCollider.CanCollide(hitbox.colliderInfo.colliderHash, hurtbox.unitCollider.owner.GetHashCode())) + continue; + hitbox.unitCollider.RecordCollision(hitbox.colliderInfo.colliderHash, hurtbox.unitCollider.owner.GetHashCode()); + hitbox.unitCollider.owner.OnHit(collision); + hurtbox.unitCollider.owner.OnGetHit(collision); + } } ListPool.Release(hitboxes); @@ -105,4 +122,85 @@ public class CollisionSystem : SingletonMB } + private void OnDrawGizmos() + { + } + } + +public static class ColliderUtility +{ + public static CollisionInfo GetCollision(ColliderDescriptor collider, ColliderDescriptor collidee) + { + CollisionInfo collision = new CollisionInfo(); + collision.collider = collider; + collision.collidee = collidee; + Box colliderBox = GetColliderInWorldSpace(collider); + Box collideeBox = GetColliderInWorldSpace(collidee); + Box intersection = GetIntersection(colliderBox, collideeBox); + collision.intersection = intersection; + collision.isCollision = intersection.size.magnitude != 0; + return collision; + } + + public static Box GetColliderInWorldSpace(ColliderDescriptor collider) + { + Box box = new Box(); + Vector3 fac = new Vector3(1, 1, collider.unitCollider.owner.transform.forward.normalized == Vector3.forward ? 1 : -1); + Vector3 unitPos = collider.unitCollider.owner.transform.position; + Vector3 pos = Vector3.zero; // gizmo位置 + Vector3 localPos = collider.colliderInfo.position; + Vector3 localSize = collider.colliderInfo.size; + var pivot = collider.colliderInfo.pivot; + switch (pivot) + { + case ColliderBox.Pivot.MiddleBottom: + localPos.y += localSize.y / 2; + break; + } + pos = unitPos + Vector3.Scale(localPos, fac); + box.center = pos; + box.size = localSize; + return box; + } + + public static Box GetIntersection(Box b1, Box b2) + { + bool isIntersection = true; + + float l1 = b1.center.x - b1.size.x / 2; + float r1 = b1.center.x + b1.size.x / 2; + float l2 = b2.center.x - b2.size.x / 2; + float r2 = b2.center.x + b2.size.x / 2; + isIntersection &= r1 >= l2 && l1 <= r2; + + float o1 = b1.center.y - b1.size.y / 2; + float t1 = b1.center.y + b1.size.y / 2; + float o2 = b2.center.y - b2.size.y / 2; + float t2 = b2.center.y + b2.size.y / 2; + isIntersection &= t1 >= o2 && o1 <= t2; + + float c1 = b1.center.z - b1.size.z / 2; + float f1 = b1.center.z + b1.size.z / 2; + float c2 = b2.center.z - b2.size.z / 2; + float f2 = b2.center.z + b2.size.z / 2; + isIntersection &= f1 >= c2 && c1 <= f2; + + if(!isIntersection) + { + return new Box(); + } + + Box box = new Box(); + float l = Mathf.Max(l1, l2); + float r = Mathf.Min(r1, r2); + float b = Mathf.Max(o1, o2); + float t = Mathf.Min(t1, t2); + float c = Mathf.Max(c1, c2); + float f = Mathf.Max(f1, f2); + box.center = new Vector3((l + r) / 2, (b + t) / 2, (c + f) / 2 ); + box.size = new Vector3(r - l, t - b, f - c); + return box; + } + +} \ No newline at end of file diff --git a/Assets/Scripts/Unit/Component/MonsterAnimation.cs b/Assets/Scripts/Unit/Component/MonsterAnimation.cs index f536c5ef..a59443e0 100644 --- a/Assets/Scripts/Unit/Component/MonsterAnimation.cs +++ b/Assets/Scripts/Unit/Component/MonsterAnimation.cs @@ -86,9 +86,15 @@ public class MonsterAnimation : UnitAnimation m_Owner.unitRootMotion.UpdateRootMotion(); } - public void AnimIdle() { m_Animator.CrossFade("Idle", 0.2f, 0); } + + public void AnimHitLight() + { + m_Animator.Play("HitLight", 0, 0); + //m_Animator.CrossFade("HitLight", 0.05f, 0, 0, 0); + } + } diff --git a/Assets/Scripts/Unit/Component/MonsterState.cs b/Assets/Scripts/Unit/Component/MonsterState.cs index 2beba0d5..b1ff9cbd 100644 --- a/Assets/Scripts/Unit/Component/MonsterState.cs +++ b/Assets/Scripts/Unit/Component/MonsterState.cs @@ -14,6 +14,7 @@ public class MonsterState : UnitState Move, + HitLight, HitAir, HitGround, HitFall, @@ -73,23 +74,25 @@ public class MonsterState : UnitState public struct LandingParam { } + public struct HitLightParam { } + #region Idle IEnumerator Idle(IdleParam param) { - if (m_Owner.isInAir) // 浮空切换到landing - { - ChangeState(EUnitState.Landing, new LandingParam()); - } - else // idle - { + //if (m_Owner.isInAir) // 浮空切换到landing + //{ + // ChangeState(EUnitState.Landing, new LandingParam()); + //} + //else // idle + //{ m_Owner.SetYPosition(0); m_Owner.monsterAnimation.AnimIdle(); while (true) { yield return null; } - } + //} } void OnIdleExit(EUnitState nextState) @@ -97,5 +100,28 @@ public class MonsterState : UnitState } #endregion + #region HitLight + + IEnumerator HitLight(HitLightParam param) + { + m_Owner.monsterAnimation.AnimHitLight(); + yield return null; + while (true) + { + bool reachEnd = m_Owner.monsterAnimation.layers[0].playbackNomralizedTime == 1; + if(reachEnd) + { + ChangeState(EUnitState.Idle, new IdleParam()); + } + yield return null; + } + } + + void OnHitLightExit(EUnitState nextState) + { + } + + #endregion + } \ No newline at end of file diff --git a/Assets/Scripts/Unit/Component/PCAnimation.cs b/Assets/Scripts/Unit/Component/PCAnimation.cs index 878c9b7c..9c2a77ec 100644 --- a/Assets/Scripts/Unit/Component/PCAnimation.cs +++ b/Assets/Scripts/Unit/Component/PCAnimation.cs @@ -152,6 +152,7 @@ public class PCAnimation : UnitAnimation public void AnimAirAttack(int id) { + m_Owner.unitCollider.OnAnimationChange(); #if ANIM_CROSS_FADE m_Animator.CrossFade("AirAttack" + id, 0.05f); #else @@ -162,6 +163,7 @@ public class PCAnimation : UnitAnimation public void AnimAttack(int id) { + m_Owner.unitCollider.OnAnimationChange(); m_Animator.CrossFade("Attack" + id, 0.05f); } diff --git a/Assets/Scripts/Unit/Component/UnitCollider.cs b/Assets/Scripts/Unit/Component/UnitCollider.cs index 8813ccef..f3170d1b 100644 --- a/Assets/Scripts/Unit/Component/UnitCollider.cs +++ b/Assets/Scripts/Unit/Component/UnitCollider.cs @@ -50,17 +50,27 @@ public class UnitCollider : UnitComponent public void OnAnimationChange() { hitMask.Clear(); - } - public void RecordCollision() + public void RecordCollision(int colliderHash, int targetHash) { + List record; + if (!hitMask.TryGetValue(colliderHash, out record)) + { + record = new List(); + hitMask.Add(colliderHash, record); + } + record.Add(targetHash); + } - } - - public bool CanCollide() + public bool CanCollide(int colliderHash, int targetHash) { - return true; + List record; + if(!hitMask.TryGetValue(colliderHash, out record)) + { + return true; + } + return !record.Contains(targetHash); } #if UNITY_EDITOR diff --git a/Assets/Scripts/Unit/Controller/MonsterController.cs b/Assets/Scripts/Unit/Controller/MonsterController.cs index ba738dfc..29ac9dcd 100644 --- a/Assets/Scripts/Unit/Controller/MonsterController.cs +++ b/Assets/Scripts/Unit/Controller/MonsterController.cs @@ -1,9 +1,21 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif public class MonsterController : UnitController { + public override UnitType type { get { return UnitType.Monster; } } + + public Vector3 center + { + get + { + return GetComponentInChildren().bounds.center; + } + } public override void Initialize(GameObject obj, string folder) { @@ -19,9 +31,34 @@ public class MonsterController : UnitController public override void Update() { base.Update(); + } - + public override void OnHit(CollisionInfo info) + { } + public override void OnGetHit(CollisionInfo info) + { + ColliderBox hitbox = info.collider.colliderInfo.collider; + Debug.Assert(hitbox.type == ColliderBox.EColliderType.HitBox); + + if(hitbox.hitResponse == ColliderBox.EHitResponse.Light) + { + monsterState.ChangeState(MonsterState.EUnitState.HitLight, new MonsterState.HitLightParam()); + } + else if(hitbox.hitResponse == ColliderBox.EHitResponse.HitAir) + { + } + + string path = hitbox.sparkPath; +#if UNITY_EDITOR + GameObject vfx = AssetDatabase.LoadAssetAtPath(path); + if(vfx != null) + { + GameObject go = GameObject.Instantiate(vfx); + go.transform.position = center; + } +#endif + } -} +} \ No newline at end of file diff --git a/Assets/Scripts/Unit/Controller/PCController.cs b/Assets/Scripts/Unit/Controller/PCController.cs index 5ad3abc1..93228d31 100644 --- a/Assets/Scripts/Unit/Controller/PCController.cs +++ b/Assets/Scripts/Unit/Controller/PCController.cs @@ -8,7 +8,9 @@ public class PCController : UnitController { public static PCController instance; - private void Awake() + public override UnitType type { get { return UnitType.PC; } } + + private void Awake() { instance = this; } @@ -29,4 +31,21 @@ public class PCController : UnitController base.Update(); } + public override void OnHit(CollisionInfo info) + { + } + + public override void OnGetHit(CollisionInfo info) + { + } + + public override void OnGrab() + { + } + + public override void OnPull() + { + } + + } diff --git a/Assets/Scripts/Unit/Controller/UnitController.cs b/Assets/Scripts/Unit/Controller/UnitController.cs index b1db29d4..3568cb4e 100644 --- a/Assets/Scripts/Unit/Controller/UnitController.cs +++ b/Assets/Scripts/Unit/Controller/UnitController.cs @@ -11,6 +11,15 @@ using UnityEngine; public class UnitController : MonoBehaviour/*, Interactable*/ { + public enum UnitType + { + PC, + Monster, + Prop, + } + + public virtual UnitType type { get; } + // 角色共有的组件 public UnitRender unitRender; @@ -106,11 +115,11 @@ public class UnitController : MonoBehaviour/*, Interactable*/ { } - public virtual void OnHit() + public virtual void OnHit(CollisionInfo info) { } - public virtual void OnHurt() + public virtual void OnGetHit(CollisionInfo info) { } @@ -118,6 +127,9 @@ public class UnitController : MonoBehaviour/*, Interactable*/ { } + public virtual void OnPull() + { + } public void SetYPosition(float y) { -- cgit v1.1-26-g67d0