From ffd1d5af496e0a0eff343b27c4f0f965bbbf79eb Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 31 Aug 2021 19:07:21 +0800 Subject: *projectile --- Assets/Scripts/Projectile/Projectile.cs | 163 +++++++++++++++++++-- Assets/Scripts/Props.meta | 8 + Assets/Scripts/Scene.meta | 8 + Assets/Scripts/Unit/Collider/CollisionSystem.cs | 53 ++++++- Assets/Scripts/Unit/Component/PCState.cs | 1 + .../Scripts/Unit/Controller/MonsterController.cs | 14 +- Assets/Scripts/Unit/Controller/UnitController.cs | 13 ++ Assets/Scripts/Unit/Events/EventProjectile.cs | 3 +- Assets/Scripts/Unit/TimelineEventProxy.cs | 46 +++++- 9 files changed, 284 insertions(+), 25 deletions(-) create mode 100644 Assets/Scripts/Props.meta create mode 100644 Assets/Scripts/Scene.meta (limited to 'Assets/Scripts') diff --git a/Assets/Scripts/Projectile/Projectile.cs b/Assets/Scripts/Projectile/Projectile.cs index 5250d049..b1eb1b61 100644 --- a/Assets/Scripts/Projectile/Projectile.cs +++ b/Assets/Scripts/Projectile/Projectile.cs @@ -2,37 +2,178 @@ using System.Collections.Generic; using UnityEngine; +public struct ProjectileInfo +{ + public UnitController owner; + public Vector3 position; + public Vector3 rotation; + public Vector3 scale; + public Vector3 direction; + public Vector3 velocity; + public bool towardDirection; + public float lifetime; + public bool useGravity; + public float gravity; + public string sparkPath; +} + public class Projectile : MonoBehaviour { + public enum EBoxType + { + Single = 0, + Multiple = 1, + Grid = 2, + } - public Box collider; + #region 序列化数据 + public EBoxType type; - public bool multiColliders; - public List colliders; + public Box collider; + public List colliders; + + public Box colliderGrid; + public Vector3 slice; + #endregion + + [HideInInspector] public UnitController owner; + [HideInInspector] public bool isActive; - public Vector3 velocity; // 初始速度 + [HideInInspector] + public Vector3 velocity; // 初始速度 + + [HideInInspector] + public float gravity; + + [HideInInspector] + public bool towardDirection; // foward朝向运动的方向 + + [HideInInspector] + public float lifetime; + + public string sparkPath; + + private List m_Hitmask; + + private float time; - public float gravity; + private bool markDestroy; - public bool towardDirection; // foward朝向运动的方向 + public void Initialize(ProjectileInfo info) + { + this.owner = info.owner; + this.transform.rotation = Quaternion.Euler(info.rotation); + this.transform.position = info.position; + this.transform.localScale.Scale(info.scale); + this.velocity = info.velocity; + this.lifetime = info.lifetime; + this.sparkPath = info.sparkPath; - void OnEnable() + markDestroy = false; + + time = 0; + + m_Hitmask = new List(); + } + + void OnEnable() { ColliderRegistry.Instance.AddProjectile(this); } - void Update() - { + public void Update() + { + Update(Time.deltaTime); + } - } + public void Update(float deltaTime) + { + this.transform.position += this.velocity * deltaTime; + time += deltaTime; + if(time > this.lifetime || markDestroy) + { + DestroyImmediate(this.gameObject); + } + } - void OnDestroy() + void OnDestroy() { ColliderRegistry.Instance.RemoveProjectile(this); } + public IEnumerable GetCollidersInWorldSpace() + { + if(type == EBoxType.Single) + { + Box box = collider; + box.center = transform.position + collider.center; + yield return box; + } + else if(type == EBoxType.Multiple) + { + for(int i = 0; i < colliders.Count; ++i) + { + Box box = colliders[i]; + box.center = transform.position + box.center; + yield return box; + } + } + else if(type == EBoxType.Grid) + { + Vector3 lowerCornor = colliderGrid.center - colliderGrid.size / 2; + Vector3 cellSize = Vector3.Scale(colliderGrid.size, new Vector3(1f / slice.x, 1f / slice.y, 1f / slice.z)); + for (int x = 0; x < slice.x; ++x) + { + for(int y = 0; y < slice.y; ++y) + { + for(int z = 0; z < slice.z; ++z) + { + Vector3 xyz = new Vector3(x, y, z); + Box box = new Box(); + box.size = cellSize; + box.center = lowerCornor + transform.position + Vector3.Scale(cellSize, xyz) + Vector3.Scale(cellSize, new Vector3(0.5f, 0.5f, 0.5f)); + yield return box; + } + } + } + } + yield break; + } + + private void OnDrawGizmos() + { + Gizmos.color = Color.red * 0.5f; + foreach(var itor in GetCollidersInWorldSpace()) + { + Box box = (Box)itor; + Gizmos.DrawCube(box.center, box.size); + } + } + + public bool CanHit(int target) + { + return !m_Hitmask.Contains(target); + } + + public void RecordTarget(int targethash) + { + m_Hitmask.Add(targethash); + } + + public void OnShot(CollisionInfo collision) + { + GameObject spark = ResourceManager.Instance.LoadAsset(sparkPath); + if (spark) + { + GameObject obj = GameObject.Instantiate(spark); + obj.transform.position = collision.collidee.unitCollider.owner.center; + + markDestroy = true; + } + } + } \ No newline at end of file diff --git a/Assets/Scripts/Props.meta b/Assets/Scripts/Props.meta new file mode 100644 index 00000000..bb96602e --- /dev/null +++ b/Assets/Scripts/Props.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f299520ed9fcf4a45858ad4ef5a8d5d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Scene.meta b/Assets/Scripts/Scene.meta new file mode 100644 index 00000000..eb7a8716 --- /dev/null +++ b/Assets/Scripts/Scene.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eaee2d0f48cff9b40baf0686a8105600 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Unit/Collider/CollisionSystem.cs b/Assets/Scripts/Unit/Collider/CollisionSystem.cs index 0e3c92f0..e84c54a9 100644 --- a/Assets/Scripts/Unit/Collider/CollisionSystem.cs +++ b/Assets/Scripts/Unit/Collider/CollisionSystem.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System; using System.Collections.Generic; using UnityEngine; @@ -8,10 +8,11 @@ public struct ColliderDescriptor public UnitCollider unitCollider; } +[Serializable] public struct Box { - public Vector3 center; - public Vector3 size; + [SerializeField] public Vector3 center; + [SerializeField] public Vector3 size; } public struct CollisionInfo @@ -107,9 +108,53 @@ public class CollisionSystem : SingletonMB void SolveProjectile() { + // collect all hurt box + List hurtboxes = ListPool.Get(); + foreach (var collider in registry.colliders) + { + ColliderInfo[] boxes = collider.GetCurrentBoxesInfoByType(ColliderBox.EColliderType.HurtBox); + if (boxes == null || boxes.Length == 0) + continue; + for (int i = 0; i < boxes.Length; ++i) + { + ColliderDescriptor descriptor = new ColliderDescriptor(); + descriptor.colliderInfo = boxes[i]; + descriptor.unitCollider = collider; + hurtboxes.Add(descriptor); + } + } - } + foreach (var projectile in registry.projectiles) + { + for(int i = 0; i < hurtboxes.Count; ++i) + { + ColliderDescriptor hurtCollider = hurtboxes[i]; + if (projectile.owner.type == hurtCollider.unitCollider.owner.type) + continue; + Box hurtbox = ColliderUtility.GetColliderInWorldSpace(hurtCollider); + foreach (var itor in projectile.GetCollidersInWorldSpace()) + { + Box box = (Box)itor; + Box intersection = ColliderUtility.GetIntersection(box, hurtbox); + if (intersection.size.magnitude == 0) + continue; + if (!projectile.CanHit(hurtCollider.unitCollider.owner.GetHashCode())) + continue; + projectile.RecordTarget(hurtCollider.unitCollider.owner.GetHashCode()); + CollisionInfo collision = new CollisionInfo(); + collision.isCollision = true; + collision.intersection = intersection; + collision.collidee = hurtCollider; + hurtCollider.unitCollider.owner.OnGetShot(collision); + projectile.OnShot(collision); + + goto next; + } + } + next:; + } + } // throwbox <-> hurtbox void SolveThrow() diff --git a/Assets/Scripts/Unit/Component/PCState.cs b/Assets/Scripts/Unit/Component/PCState.cs index 1b01fad8..a9252e26 100644 --- a/Assets/Scripts/Unit/Component/PCState.cs +++ b/Assets/Scripts/Unit/Component/PCState.cs @@ -457,3 +457,4 @@ public class PCState : UnitState #endregion } + \ No newline at end of file diff --git a/Assets/Scripts/Unit/Controller/MonsterController.cs b/Assets/Scripts/Unit/Controller/MonsterController.cs index 981e6d4b..9e7e7955 100644 --- a/Assets/Scripts/Unit/Controller/MonsterController.cs +++ b/Assets/Scripts/Unit/Controller/MonsterController.cs @@ -6,14 +6,6 @@ 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) { base.Initialize(obj, folder); @@ -58,4 +50,10 @@ public class MonsterController : UnitController } } + public override void OnGetShot(CollisionInfo info) + { + monsterState.ChangeState(MonsterState.EUnitState.HitLight, new MonsterState.HitLightParam()); + } + + } \ No newline at end of file diff --git a/Assets/Scripts/Unit/Controller/UnitController.cs b/Assets/Scripts/Unit/Controller/UnitController.cs index 3568cb4e..9b3ef6e5 100644 --- a/Assets/Scripts/Unit/Controller/UnitController.cs +++ b/Assets/Scripts/Unit/Controller/UnitController.cs @@ -83,6 +83,14 @@ public class UnitController : MonoBehaviour/*, Interactable*/ } } + public virtual Vector3 center + { + get + { + return GetComponentInChildren().bounds.center; + } + } + public virtual void Initialize( GameObject obj , string folder) { unitObj = obj; @@ -123,6 +131,11 @@ public class UnitController : MonoBehaviour/*, Interactable*/ { } + public virtual void OnGetShot(CollisionInfo info) + { + } + + public virtual void OnGrab() { } diff --git a/Assets/Scripts/Unit/Events/EventProjectile.cs b/Assets/Scripts/Unit/Events/EventProjectile.cs index 7dc2923a..0c1dc22b 100644 --- a/Assets/Scripts/Unit/Events/EventProjectile.cs +++ b/Assets/Scripts/Unit/Events/EventProjectile.cs @@ -24,7 +24,7 @@ public class EventProjectile : AnimationEventBase public Vector3 rotation; [Tooltip("Scale")] - public Vector3 scale; + public Vector3 scale = Vector3.one; [Tooltip("初始速度")] public Vector3 velocity; @@ -35,5 +35,6 @@ public class EventProjectile : AnimationEventBase [Tooltip("击中效果")] public ColliderBox.EHitResponse hitResponse; + public string sparkPath; } diff --git a/Assets/Scripts/Unit/TimelineEventProxy.cs b/Assets/Scripts/Unit/TimelineEventProxy.cs index 7a76cd73..51d437fe 100644 --- a/Assets/Scripts/Unit/TimelineEventProxy.cs +++ b/Assets/Scripts/Unit/TimelineEventProxy.cs @@ -7,7 +7,13 @@ using UnityEngine; // 执行帧事件 [DisallowMultipleComponent] public partial class TimelineEventProxy -{ +{ +#if UNITY_EDITOR // ActionTool里 + public bool isInEditMode; + public delegate void RegisterProjectileHandle(Projectile projectile); + public RegisterProjectileHandle registerProjectile; +#endif + public enum EEventType { EventCamera_Zoom, // 相机聚焦 @@ -118,4 +124,42 @@ public partial class TimelineEventProxy } + void EventProjectile(AnimationEventBase animEvent) + { + EventProjectile e = animEvent as EventProjectile; + if (e == null) + return; + string projectilePath = e.projectilePath; + GameObject prefab = ResourceManager.Instance.LoadAsset(projectilePath); + if(prefab == null) + { + LogHelper.LogError("缺少对应的projectile, " + projectilePath); + return; + } + if(prefab.GetComponent() == null) + { + LogHelper.LogError("没有projectile脚本"); + return; + } + GameObject obj = GameObject.Instantiate(prefab); + Projectile projectile = obj.GetComponent(); + ProjectileInfo info = new ProjectileInfo(); + info.owner = m_Owner; + info.position = m_Root.transform.position + e.posOffset; + info.rotation = e.rotation; + info.scale = e.scale; + info.direction = Vector3.right; + info.velocity = Vector3.right * 10f; + info.lifetime = 5; + info.sparkPath = e.sparkPath; + projectile.Initialize(info); + +#if UNITY_EDITOR + if(isInEditMode && registerProjectile != null) + { + registerProjectile(projectile); + } +#endif + } + } \ No newline at end of file -- cgit v1.1-26-g67d0