using System.Collections; using System.Collections.Generic; using UnityEngine; public struct ProjectileInfo { public string name; public string tag; public EventProjectile.EMoveType moveType; public UnitController owner; public Vector3 position; public Vector3 rotation; public Vector3 scale; public Vector3 velocity; public Vector3 acceleration; public bool towardDirection; public float lifetime; public bool useGravity; public string sparkPath; } public class Projectile : MonoBehaviour { public enum EBoxType { Single = 0, Multiple = 1, Grid = 2, } #region 序列化数据 public EBoxType type; public Box collider; public List colliders; public Box colliderGrid; public Vector3 slice; #endregion //名字,可以用来识别这个projectile public new string name; //标签,可以用来做一些标记 public new string tag; public EventProjectile.EMoveType moveType; [HideInInspector] public UnitController owner; [HideInInspector] public bool isActive; [HideInInspector] public Vector3 velocity; // 初始速度 [HideInInspector] public Vector3 acceleration; // 加速度 [HideInInspector] public bool towardDirection; // foward朝向运动的方向 [HideInInspector] public float lifetime; public string sparkPath; private List m_Hitmask; public float time; private bool markDestroy; public void Initialize(ProjectileInfo info) { this.name = info.name; this.tag = info.tag; this.moveType = info.moveType; 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.acceleration = info.acceleration; this.lifetime = info.lifetime; this.sparkPath = info.sparkPath; markDestroy = false; time = 0; m_Hitmask = new List(); } void OnEnable() { ColliderRegistry.Instance.AddProjectile(this); } public void Update() { Update(Time.deltaTime); } public void Update(float deltaTime) { if(moveType == EventProjectile.EMoveType.Kinematic) { this.velocity += this.acceleration * deltaTime; this.transform.position += this.velocity * deltaTime; } time += deltaTime; if (time > this.lifetime || markDestroy) { DestroyImmediate(this.gameObject); } } 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); #if UNITY_EDITOR obj.transform.SetParent(TimelineEventProxy.Root_Particles.transform); #endif obj.transform.position = collision.collidee.unitCollider.owner.center; markDestroy = true; } } public bool HasTag(string tag) { return this.tag != null && this.tag.Contains(tag); } }