488 lines
11 KiB
C#
488 lines
11 KiB
C#
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<int> CheckTargetDict = new HashSet<int>();
|
|
protected List<GameObject> CheckTargetList = new List<GameObject>();
|
|
protected bool IsSearchByCollider = false;
|
|
protected List<BattleContinuousTarget> ContinuousTargetsList = new List<BattleContinuousTarget>();
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |