c1_unity/Assets/Scripts/Component/Battle/BattleControlBullet.cs
2023-04-03 11:04:31 +08:00

399 lines
10 KiB
C#

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<int> CheckTargetDict = new HashSet<int>();
protected List<GameObject> CheckTargetList = new List<GameObject>();
protected List<BattleContinuousTarget> ContinuousTargetsList = new List<BattleContinuousTarget>();
[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;
}
}
}