using UnityEngine; using System.Collections.Generic; namespace BF { public class BattleContinuousTarget { public GameObject Unit; public float Time; } public class BattleControlCollider : MonoBehaviour { protected BattleControlUnit admin; public int uniqueId = 0; protected bool isActive = false; protected int checkType = 0; protected float checkInterval = 0.0f; protected float checkDuration = 0.0f; protected int skillId = 0; protected int cloneIndex = 0; protected int skillEffectIndex = 0; protected bool unlimitCount = false; protected float delayAimTime = 0.0f; protected float aimFollowTime = 0.0f; protected float aimFollowSpeed = 0.0f; protected bool aimFollow = false; protected bool delayAim = false; protected bool effectOver = false; protected bool waitRecycle = false; protected Vector3 offset = Vector3.zero; protected Vector3 targetPosition = Vector3.zero; protected BattleControlUnit lockTarget; protected bool isLockTarget = false; protected HashSet CheckTargetDict = new HashSet(); protected List CheckTargetList = new List(); protected bool IsSearchByCollider = false; protected List ContinuousTargetsList = new List(); protected BattleControlColliderContainer container; private bool updatePositionWithLockTarget = false; [System.NonSerialized] public float CacheX = 0.0f; [System.NonSerialized] public float CacheY = 0.0f; [System.NonSerialized] public float CacheZ = 0.0f; [System.NonSerialized] private static Vector2 Vector2A = Vector2.zero; private static Vector2 Vector2B = Vector2.zero; [System.NonSerialized] public bool IsRecycle = false; public virtual void SetColliderEnabled(bool enabled) {} public virtual void Recycle() {} public void SetContainer(BattleControlColliderContainer container) { this.container = container; } public void RemoveFromContainer() { this.container = null; } public void SetIsSearchByCollider(bool isSearchByCollider) { IsSearchByCollider = isSearchByCollider; } public void SetAdmin(BattleControlUnit unit) { admin = unit; if (admin.Side == 1) { gameObject.layer = BattleConst.LAYER_ATK_BULLET; } else { gameObject.layer = BattleConst.LAYER_DEF_BULLET; } } public int GetUniqueId() { return uniqueId; } public void SetTargetPosition(Vector3 position) { targetPosition = position; } public void SetLockTarget(BattleControlUnit unit) { lockTarget = unit; isLockTarget = true; } public void SetUpdatePositionWithLockTarget(bool updatePositionWithLockTarget) { this.updatePositionWithLockTarget = updatePositionWithLockTarget; } public void InitPosition(float x, float y, float z) { if (admin.Direction == 1) { transform.position = new Vector3(x, y, z) + offset; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { transform.position = new Vector3(x, y, z) - offset; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } private void MoveToLockTargetPosition(float deltaTime) { if (admin.Direction == 1) { var position = lockTarget.transform.position + offset; var moveToPosition = Vector3.MoveTowards(transform.position, position, aimFollowSpeed * deltaTime); transform.position = moveToPosition; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { var position = lockTarget.transform.position - offset; var moveToPosition = Vector3.MoveTowards(transform.position, position, aimFollowSpeed * deltaTime); transform.position = moveToPosition; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } private void MoveToTargetPosition(float deltaTime) { if (admin.Direction == 1) { var position = targetPosition + offset; var moveToPosition = Vector3.MoveTowards(transform.position, position, aimFollowSpeed * deltaTime); transform.position = moveToPosition; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { var position = targetPosition - offset; var moveToPosition = Vector3.MoveTowards(transform.position, position, aimFollowSpeed * deltaTime); transform.position = moveToPosition; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } private void UpdatePositionByTargetPosition() { if (admin.Direction == 1) { transform.position = targetPosition + offset; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { transform.position = targetPosition - offset; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } private void UpdatePositionByLockTargetPosition() { if (admin.Direction == 1) { transform.position = lockTarget.transform.position + offset; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { transform.position = lockTarget.transform.position - offset; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } private void UpdatePositionByAdminPosition() { if (admin.Direction == 1) { transform.position = admin.transform.position + offset; transform.localEulerAngles = new Vector3(0.0f, 0.0f, 0.0f); } else { transform.position = admin.transform.position - offset; transform.localEulerAngles = new Vector3(0.0f, 180.0f, 0.0f); } } public void CachePosition() { var position = transform.position; CacheX = position.x; CacheY = position.y; CacheZ = position.z; } private void FollowTarget(float deltaTime) { if (isLockTarget) { MoveToLockTargetPosition(deltaTime); } else { MoveToTargetPosition(deltaTime); } } public void InitBase() { CheckTargetDict.Clear(); CheckTargetList.Clear(); ContinuousTargetsList.Clear(); effectOver = false; waitRecycle = false; lockTarget = null; isLockTarget = false; updatePositionWithLockTarget = false; } public void Search(int checkType, float interval, float duration, int skillId, int cloneIndex, int skillEffectIndex, bool unlimitCount, float delayAimTime, float aimFollowTime, float aimFollowSpeed, bool disposable) { this.checkType = checkType; this.checkInterval = interval; this.checkDuration = duration; this.skillId = skillId; this.cloneIndex = cloneIndex; this.skillEffectIndex = skillEffectIndex; this.unlimitCount = unlimitCount; this.delayAimTime = delayAimTime; this.aimFollowTime = aimFollowTime; this.aimFollowSpeed = aimFollowSpeed; if (aimFollowTime > 0.0f) { aimFollow = true; } else { aimFollow = false; } if (isLockTarget) { UpdatePositionByLockTargetPosition(); } else { UpdatePositionByTargetPosition(); } if (disposable) { delayAim = false; StartSearch(); } else { if (delayAimTime > 0.0f) // 延迟 { delayAim = true; } else // 立即 { delayAim = false; } } } public void StartSearch() { if (IsSearchByCollider) { isActive = true; effectOver = false; waitRecycle = false; SetColliderEnabled(true); } } private void OnTriggerEnter(Collider other) { var id = other.gameObject.GetInstanceID(); if (!CheckTargetDict.TryAdd(id)) { return; } CheckTargetList.Add(other.gameObject); if (checkInterval > 0.000001f) // 持续型范围技能,进入范围的时候立即生效一次 { admin.OnHitTarget(other.gameObject, skillId, cloneIndex, skillEffectIndex); var target = BF.BFMain.Instance.BattleMgr.PoolHelper.GetContinuousTarge(); target.Unit = other.gameObject; target.Time = checkInterval; ContinuousTargetsList.Add(target); } } private void OnTriggerExit(Collider other) { var gameObject = other.gameObject; var id = gameObject.GetInstanceID(); if (CheckTargetDict.Contains(id)) { CheckTargetList.Remove(gameObject); if (checkInterval > 0.000001f) // 持续型范围技能,进入范围的时候立即生效一次 { var count = ContinuousTargetsList.Count; for (int i = 0; i < count; i++) { if (gameObject == ContinuousTargetsList[i].Unit) { ContinuousTargetsList.RemoveAt(i); break; } } } } } public void AddCheckTargetList(GameObject gameObject) { CheckTargetList.Add(gameObject); } private void SearchNearestTarget() { var control = BF.BFMain.Instance.BattleMgr.GetNearestUnit(admin.Side); if(ReferenceEquals(control, null)) { Recycle(); return; } CheckTargetList.Add(control.gameObject); } private void SearchAllTargets() { var unitsList = BF.BFMain.Instance.BattleMgr.GetUnitsList(admin.Side); for (int i = 0; i < unitsList.Count; i++) { CheckTargetList.Add(unitsList[i].gameObject); } } protected void CheckCollider() { CheckSurroundingTargets(); } private void CheckSurroundingTargets() { if (checkInterval <= 0.000001f) { if (effectOver) { if (waitRecycle) { if (!unlimitCount) { FindNearestAndHit(); } else { HitTargets(); } Recycle(); } else { waitRecycle = true; } } else { effectOver = true; } } } protected void FindNearestAndHit() { var count = CheckTargetList.Count; if (count <= 0) { return; } GameObject unit = null; var position = admin.transform.position; Vector2A.Set(position.x, position.z); float minDis = float.MaxValue; for(int j = 0; j < count; j++) { var objB = CheckTargetList[j]; Vector2B.Set(objB.transform.position.x, objB.transform.position.z); var dis = (Vector2B - Vector2A).sqrMagnitude; if (dis < minDis) { minDis = dis; unit = objB; } } if (!ReferenceEquals(unit, null)) { admin.OnHitTarget(unit, skillId, cloneIndex, skillEffectIndex); } } private void HitTargets() { var count = CheckTargetList.Count; if (count <= 0) { return; } for (int i = count - 1; i >= 0; i--) { admin.OnHitTarget(CheckTargetList[i], skillId, cloneIndex, skillEffectIndex); } } public int GetSearchTargetsCount() { return CheckTargetList.Count; } public int GetTargetId(int index) { if (index >= 0 && index < CheckTargetList.Count) { return CheckTargetList[index].GetInstanceID(); } return 0; } private void Update() { if (delayAim) { delayAimTime -= Time.deltaTime*BattleConfigure.TimeScale; if (delayAimTime < 0.0f) { delayAim = false; } return; } if (aimFollow) { var deltaTime = Time.deltaTime*BattleConfigure.TimeScale; aimFollowTime -= deltaTime; if (aimFollowTime < 0.0f) { aimFollow = false; } FollowTarget(deltaTime); } if (!isActive) { return; } if (updatePositionWithLockTarget) { UpdatePositionByLockTargetPosition(); } var count = ContinuousTargetsList.Count; if (count <= 0) { return; } BattleContinuousTarget target = null; var deltaTime2 = Time.deltaTime*BattleConfigure.TimeScale; for (int i = count - 1; i >= 0; i--) { target = ContinuousTargetsList[i]; target.Time -= deltaTime2; if (target.Time <= 0.0f) { target.Time = checkInterval; admin.OnHitTarget(target.Unit, skillId, cloneIndex, skillEffectIndex); } } } } }