223 lines
6.5 KiB
C#
223 lines
6.5 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using DG.Tweening;
|
||
using DragonLi.Core;
|
||
using UnityEngine;
|
||
using Random = UnityEngine.Random;
|
||
|
||
public enum EggBulletType
|
||
{
|
||
EnemyType,
|
||
PlayerType,
|
||
}
|
||
|
||
public class EggBullet : MonoBehaviour
|
||
{
|
||
public EggBulletType type;
|
||
|
||
public bool isDie;
|
||
public bool isStop;
|
||
private Transform _enemyTran;
|
||
private Transform _playerTran;
|
||
|
||
public enum FlyMode { Straight=1, Bouncing=2, CurvedFromSide=3 }
|
||
[Header("Common Settings")]
|
||
public FlyMode flyMode = FlyMode.Straight;
|
||
public Vector3 target;
|
||
private float speed = 3f;
|
||
private float speed2 = 1.5f;
|
||
private float speed3 = 0.5f;
|
||
private float arrivalThreshold = 0.1f; // 到达目标的容差
|
||
|
||
[Header("Bouncing Mode Settings")]
|
||
private int bounceCount = 3; // 弹跳次数
|
||
private float bounceHeight = 1.5f; // 弹跳高度
|
||
|
||
[Header("Curved Mode Settings")]
|
||
private float sideOffset = 1; // 起始侧向偏移
|
||
private float curveHeight = 0.5f; // 弧线高度
|
||
public bool startFromLeft = true; // 从左侧还是右侧
|
||
|
||
private Vector3 startPos;
|
||
private Vector3 endPos;
|
||
private float startTime;
|
||
private float journeyLength;
|
||
|
||
public void Init()
|
||
{
|
||
type = EggBulletType.EnemyType;
|
||
isDie = false;
|
||
int id = Random.Range(1, 4);
|
||
//id = 3;
|
||
flyMode = (FlyMode)id;
|
||
_enemyTran = GameManager.Ins.enemy.body;
|
||
_playerTran = GameLocal.Ins.self.transform;
|
||
float targetX = Random.Range(-1f,2);
|
||
Vector3 curTarget=_playerTran.position+new Vector3(targetX,0,0);
|
||
Launch(curTarget);
|
||
}
|
||
|
||
public void ChangeType(EggBulletType curType)
|
||
{
|
||
type = curType;
|
||
}
|
||
|
||
private void OnTriggerEnter(Collider other)
|
||
{
|
||
if (other.tag == "Skillet"&& type == EggBulletType.EnemyType)
|
||
{
|
||
ChangeType(EggBulletType.PlayerType);
|
||
flyMode=FlyMode.Straight;
|
||
speed = 6f;
|
||
Launch(_enemyTran.position);
|
||
GameManager.Ins.playerRightHand.ShowSkilletEx();
|
||
}
|
||
|
||
}
|
||
|
||
public void Hit()
|
||
{
|
||
isDie = true;
|
||
Destroy(gameObject);
|
||
}
|
||
|
||
// 发射方法
|
||
public void Launch( Vector3 targetTransform)
|
||
{
|
||
target = targetTransform;
|
||
startPos = transform.position;
|
||
_vector3Start = GameManager.Ins.enemy.hand.position;
|
||
if (flyMode == FlyMode.CurvedFromSide)
|
||
{
|
||
// 计算侧向起点
|
||
Vector3 dirToTarget = (target - transform.position).normalized;
|
||
Vector3 sideDir = startFromLeft ? -Vector3.Cross(dirToTarget, Vector3.up) : Vector3.Cross(dirToTarget, Vector3.up);
|
||
startPos = target + sideDir * sideOffset;
|
||
transform.position = startPos;
|
||
}
|
||
endPos = target;
|
||
startTime = Time.time;
|
||
journeyLength = Vector3.Distance(startPos, endPos);
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
float distToEndPos = Vector3.Distance(transform.position.ReflectVectorXOZ(), endPos.ReflectVectorXOZ());
|
||
float disToTarget= Vector3.Distance(transform.position.ReflectVectorXOZ(), target.ReflectVectorXOZ());
|
||
if (disToTarget <= arrivalThreshold)
|
||
{
|
||
if (type == EggBulletType.PlayerType)
|
||
{
|
||
GameManager.Ins.EnemyHit(transform.position);
|
||
}
|
||
int index= Random.Range(0, 2);
|
||
if (type == EggBulletType.EnemyType&&index==0)
|
||
{
|
||
GameManager.Ins.PlayerHit();
|
||
}
|
||
Hit();
|
||
return;
|
||
}
|
||
if (distToEndPos <= arrivalThreshold&& type== EggBulletType.EnemyType)
|
||
{
|
||
// 到达目标,停止或销毁
|
||
OnArrival();
|
||
return;
|
||
}
|
||
|
||
switch (flyMode)
|
||
{
|
||
case FlyMode.Straight:
|
||
FlyStraight();
|
||
break;
|
||
case FlyMode.Bouncing:
|
||
FlyBouncing();
|
||
break;
|
||
case FlyMode.CurvedFromSide:
|
||
FlyCurved();
|
||
break;
|
||
}
|
||
}
|
||
|
||
|
||
void FlyStraight()
|
||
{
|
||
float frac = (Time.time - startTime) * speed / journeyLength;
|
||
transform.position = Vector3.Lerp(startPos, endPos, frac);
|
||
}
|
||
|
||
void FlyBouncing()
|
||
{
|
||
// 总共分成:1 段下落 + bounceCount 段弹跳
|
||
int segments = bounceCount + 1;
|
||
float frac = (Time.time - startTime) * speed2 / journeyLength;
|
||
frac = Mathf.Clamp01(frac);
|
||
|
||
// 水平线性插值
|
||
Vector3 horizontalPos = Vector3.Lerp(startPos, endPos, frac);
|
||
|
||
// 计算当前处于哪个“段”和在该段内的进度 t(0~1)
|
||
float segmentLength = 1f / segments;
|
||
int segIndex = Mathf.Min((int)(frac / segmentLength), segments - 1);
|
||
float t = (frac - segIndex * segmentLength) / segmentLength;
|
||
|
||
float y;
|
||
if (segIndex == 0)
|
||
{
|
||
// 初始下落:用半个余弦曲线 y = startY * cos(t * PI/2)
|
||
y = startPos.y * Mathf.Cos(t * (Mathf.PI / 2));
|
||
}
|
||
else
|
||
{
|
||
// 弹跳段:用正弦波 y = sin(t * PI) * bounceHeight
|
||
y = Mathf.Sin(t * Mathf.PI) * bounceHeight;
|
||
}
|
||
|
||
// 最终位置
|
||
transform.position = new Vector3(horizontalPos.x,
|
||
y,
|
||
horizontalPos.z);
|
||
}
|
||
|
||
private Vector3 _vector3Start;
|
||
void FlyCurved()
|
||
{
|
||
// 进度 0→1
|
||
float frac = (Time.time - startTime) * speed3 / journeyLength;
|
||
frac = Mathf.Clamp01(frac);
|
||
|
||
// 起点和终点
|
||
Vector3 P0 = _vector3Start;
|
||
Vector3 P2 = endPos;
|
||
|
||
// 计算侧向方向(和水平面法线叉乘)
|
||
Vector3 dir = (P2 - P0).normalized;
|
||
Vector3 sideDir = startFromLeft
|
||
? -Vector3.Cross(dir, Vector3.up)
|
||
: Vector3.Cross(dir, Vector3.up);
|
||
|
||
// 控制点:在中点向侧面偏移,并抬高 curveHeight
|
||
Vector3 mid = Vector3.Lerp(P0, P2, 0.5f);
|
||
Vector3 P1 = mid + sideDir * sideOffset + Vector3.up * curveHeight;
|
||
|
||
// 二次贝塞尔公式 B(t) = (1−t)²P0 + 2(1−t)tP1 + t²P2
|
||
float u = 1 - frac;
|
||
Vector3 pos = u*u * P0
|
||
+ 2*u*frac * P1
|
||
+ frac*frac * P2;
|
||
|
||
transform.position = pos;
|
||
}
|
||
|
||
// 到达目标的回调,可扩展
|
||
protected virtual void OnArrival()
|
||
{
|
||
// 例如:爆炸、伤害、销毁等
|
||
//Destroy(gameObject);
|
||
Debug.Log("删除鸡蛋");
|
||
if(!isDie)
|
||
Destroy(gameObject);
|
||
}
|
||
}
|