using UnityEngine; using System.Collections.Generic; namespace BF { public class BattleControlBullet : MonoBehaviour { protected BattleControlUnit admin; protected int bulletType = 0; protected int bulletFinishType = 0; protected int bulletOriginType = 0; protected int searchType = 0; protected float radius = 0.0f; protected float duration = 0.0f; protected float width = 0.0f; protected float height = 0.0f; protected float speed = 0.0f; protected float offsetX = 0.0f; protected float offsetZ = 0.0f; protected float checkInterval = 0.0f; protected float checkDuration = 0.0f; protected int skillId = 0; protected int cloneIndex = 0; protected int skillEffectIndex = 0; protected Vector3 offset = Vector3.zero; protected Vector3 targetPosition = Vector3.zero; protected BattleControlUnit targetUnit; protected HashSet CheckTargetDict = new HashSet(); protected List CheckTargetList = new List(); protected List ContinuousTargetsList = new List(); [System.NonSerialized] public float CacheX = 0.0f; [System.NonSerialized] public float CacheY = 0.0f; [System.NonSerialized] public float CacheZ = 0.0f; [System.NonSerialized] public bool IsRecycle = false; private bool endWithTime = false; private bool endWithArrive = false; private bool waitNextFixedFrame = false; private bool nextFixedFrameTakeEffect = false; private bool isOver = false; private bool lockTarget = false; private int fxId = 0; private float fxDelayTime = 0.0f; private bool checkFx = false; public virtual void SetColliderEnabled(bool enabled) {} public virtual void Recycle() {} public virtual void SetupBoxCollisionBody(float collisionWidth, float collisionHeight) {} public virtual void SetupSphereCollisionBody(float collisionRadius) {} 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 void CachePosition() { var position = transform.position; CacheX = position.x; CacheY = position.y; CacheZ = position.z; } public void CacheTargetPosition() { CacheX = targetPosition.x; CacheZ = targetPosition.z; } public void InitSphereBullet(int skillId, int cloneIndex, int skillEffectIndex, int bulletType, int bulletFinishType, int bulletOriginType, int searchType, float radius, float duration, float speed, float offsetX, float offsetZ) { this.skillId = skillId; this.cloneIndex = cloneIndex; this.skillEffectIndex = skillEffectIndex; this.bulletType = bulletType; this.bulletFinishType = bulletFinishType; this.bulletOriginType = bulletOriginType; this.searchType = searchType; this.radius = radius; this.duration = duration; this.speed = speed; this.offsetX = offsetX; this.offsetZ = offsetZ; offset = new Vector3(offsetX, 0.0f, offsetZ); if (bulletFinishType == 1) // 飞到目标点才算完成,此时有速度和时间互斥 { if (speed < 0.000001f) { endWithTime = true; endWithArrive = false; } else { endWithTime = false; endWithArrive = true; } } else // 按时间算结束 { endWithTime = true; endWithArrive = false; } SetupSphereCollisionBody(radius); InitBase(); StartSearch(); } public void InitBoxBullet(int skillId, int cloneIndex, int skillEffectIndex, int bulletType, int bulletFinishType, int bulletOriginType, int searchType, float w, float h, float duration, float speed, float offsetX, float offsetZ) { this.skillId = skillId; this.skillEffectIndex = skillEffectIndex; this.bulletType = bulletType; this.bulletFinishType = bulletFinishType; this.bulletOriginType = bulletOriginType; this.searchType = searchType; this.width = w; this.height = h; this.duration = duration; this.speed = speed; this.offsetX = offsetX; this.offsetZ = offsetZ; offset = new Vector3(offsetX, 0.0f, offsetZ); if (bulletFinishType == 1) // 飞到目标点才算完成,此时有速度和时间互斥 { if (speed < 0.000001f) { endWithTime = true; endWithArrive = false; } else { endWithTime = false; endWithArrive = true; } } else // 按时间算结束 { endWithTime = true; endWithArrive = false; } SetupBoxCollisionBody(w, h); InitBase(); StartSearch(); } private void InitBase() { CheckTargetDict.Clear(); CheckTargetList.Clear(); ContinuousTargetsList.Clear(); waitNextFixedFrame = false; nextFixedFrameTakeEffect = false; isOver = false; targetUnit = null; lockTarget = false; checkFx = false; } private void StartSearch() { if (bulletOriginType == 2) { transform.position = admin.transform.position; } else { if (!ReferenceEquals(admin.Target, null)) { transform.position = admin.Target.transform.position; } } switch (searchType) { case 1: // 以目标为目标点 SearchWithTarget(); break; case 2: // 以自身为目标点 SearchWitchSelf(); break; case 3: // 以目标为目标 lockTarget = true; targetUnit = admin.Target; targetPosition = targetUnit.transform.position; break; default: break; } if (endWithTime && speed < 0.000001f) { speed = (targetPosition - transform.position).magnitude / duration; } if (bulletType == 1) // 立即开始检测碰撞 { SetColliderEnabled(true); } } private void SearchWithTarget() { if (admin.Direction == 1) { targetPosition = admin.Target.transform.position + new Vector3(offsetX, 0.0f, offsetZ); } else { targetPosition = admin.Target.transform.position + new Vector3(-offsetX, 0.0f, offsetZ); } } private void SearchWitchSelf() { if (admin.Direction == 1) { targetPosition = admin.transform.position + new Vector3(offsetX, 0.0f, offsetZ); } else { targetPosition = admin.transform.position + new Vector3(-offsetX, 0.0f, offsetZ); } } private void OnTriggerEnter(Collider other) { var id = other.gameObject.GetInstanceID(); if (!CheckTargetDict.TryAdd(id)) { return; } admin.OnHitTarget(other.gameObject, skillId, cloneIndex, skillEffectIndex); CheckTargetList.Add(other.gameObject); if (checkInterval > 0.000001f) // 持续型范围技能,进入范围的时候立即生效一次 { 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 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 (checkFx) { fxDelayTime -= Time.deltaTime*BattleConfigure.TimeScale; if (fxDelayTime < 0.0f) { checkFx = false; BF.BFMain.Instance.BattleMgr.PlayFx(fxId, admin.Direction, transform.position.x, transform.position.z); } } if (endWithTime) // 按时间结束 { duration -= Time.deltaTime*BattleConfigure.TimeScale; if (duration < 0.0f) { if (bulletType == 1) { Recycle(); } else if(bulletType == 2) { if (waitNextFixedFrame) { if (nextFixedFrameTakeEffect) { Recycle(); } } else { waitNextFixedFrame = true; SetColliderEnabled(true); } } } } else // 按飞行速度到达目标点后结束 { if (!isOver) { if ((transform.position - targetPosition).sqrMagnitude < 0.0001f) { isOver = true; } } else { if (bulletType == 1) { Recycle(); } else if(bulletType == 2) { if (waitNextFixedFrame) { if (nextFixedFrameTakeEffect) { Recycle(); } } else { waitNextFixedFrame = true; SetColliderEnabled(true); } } } } } private void FixedUpdate() { if (waitNextFixedFrame) { nextFixedFrameTakeEffect = true; } Vector3 moveToPosition; if (lockTarget) { targetPosition = admin.Target.transform.position; moveToPosition = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.fixedDeltaTime * BattleConfigure.TimeScale); } else { moveToPosition = Vector3.MoveTowards(transform.position, targetPosition, speed * Time.fixedDeltaTime * BattleConfigure.TimeScale); } if (moveToPosition.x < BattleConfigure.SceneMinX) // 撞左边墙了 { moveToPosition.x = BattleConfigure.SceneMinX; } else if (moveToPosition.x > BattleConfigure.SceneMaxX) // 撞右边墙了 { moveToPosition.x = BattleConfigure.SceneMaxX; } if (moveToPosition.z < BattleConfigure.SceneMinZ) // 撞下面墙了 { moveToPosition.z = BattleConfigure.SceneMinZ; } else if (moveToPosition.z > BattleConfigure.SceneMaxZ) // 撞上面墙了 { moveToPosition.z = BattleConfigure.SceneMaxZ; } transform.position = moveToPosition; } public void PlayTargetPointFx(int id, float delay) { checkFx = true; fxId = id; fxDelayTime = delay; } } }