add:添加魔鬼鱼,红包,鲨鱼事件等

This commit is contained in:
bzx
2026-02-11 19:07:13 +08:00
parent 2ba9a15c69
commit 33991b16b8
214 changed files with 44836 additions and 138130 deletions

View File

@@ -27,7 +27,7 @@ public class Fish : MonoBehaviour
private Vector3 localOffset;
private Transform modelRoot;
private FishState state = FishState.Alive;
public FishState state = FishState.Alive;
private bool unregisterCalled = false;
@@ -40,10 +40,33 @@ public class Fish : MonoBehaviour
Data = data;
fishGroup = curGroup;
localOffset = offset;
// 用一个子节点来偏移(非常关键)
modelRoot = transform.GetChild(0);
if (data.FishId == 11)
{
}
else
{
SetCollider(spline);
}
GameManager.Ins.fishSpawner.RegisterFish(this);
}
public void SetCollider(CurvySpline spline)
{
controller = GetComponent<SplineController>();
if(controller==null)
return;
controller.Spline = spline;
controller.Speed = data.Speed/GameManager.Ins.fishSpawner.fishSpeed;
if (Data.FishId == 12)
{
controller.Spline = GameInit.Ins.surroundSpline;
AngelHouse();
}
controller.Speed = Data.Speed/GameManager.Ins.fishSpawner.fishSpeed;
controller.Position = 0;
controller.Play();
@@ -51,11 +74,19 @@ public class Fish : MonoBehaviour
{
OnSplineEnd();
});
}
// 用一个子节点来偏移(非常关键)
modelRoot = transform.GetChild(0);
/// <summary>
/// 天使马
/// </summary>
public void AngelHouse()
{
GameManager.Ins.PlaySound3D("天使马出场",transform);
}
public void Shark()
{
GameManager.Ins.fishSpawner.RegisterFish(this);
}
void LateUpdate()
@@ -78,31 +109,46 @@ public class Fish : MonoBehaviour
if (state != FishState.Alive)
return;
float hit = (gunLevel * (1 - GameManager.Ins.Taxation) / Data.CoinValue) * 100;
float hitIndex = Random.Range(0, 101);
// 🌟 清晰的命中率计算
float taxRate = 0.05f; // 5% 抽税
float actualHitRate = gunLevel * (1 - taxRate)/ Data.CoinValue; // 实际命中率(扣除抽税)
float hitProbability = actualHitRate * 100f; // 转换为百分比概率
if (hit < hitIndex)
// 🌟 更直观的随机判断
float randomValue = Random.Range(0f, 100f);
Debug.Log($"命中率:{hitProbability:F2}%");
Debug.Log($"随机值:{randomValue:F2}");
// 如果随机值大于命中概率,则未命中
if (randomValue > hitProbability)
{
Debug.Log("未命中!");
return;
}
// 🌟 进入捕捉状态
state = FishState.Captured;
// 停止移动 & 碰撞
controller.enabled = false;
if(controller != null)
controller.enabled = false;
if (collider)
collider.enabled = false;
// 从全局容器移除(此时已经不参与任何逻辑)
// 从全局容器移除
SafeUnregister();
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
SpawnCoinPile();
if (Data.FishId == 12)
GameManager.Ins.CreateFireworks(transform.position);
RemoveInternal();
}, 1.5f);
}
void OnSplineEnd()
public void OnSplineEnd()
{
if (state != FishState.Alive)
return;
@@ -126,7 +172,8 @@ public class Fish : MonoBehaviour
if (fishGroup != null)
fishGroup.CheckAllFish();
if(Data.FishId == 12)
GameManager.Ins.ClearItem();
Destroy(gameObject);
}
@@ -160,9 +207,10 @@ public class Fish : MonoBehaviour
pileGO.GetComponent<CoinPileController>()
.Init(
GameInit.Ins.showPos,
GameInit.Ins.self.RightHand,
finalCoin
);
}
/// <summary>
@@ -172,7 +220,8 @@ public class Fish : MonoBehaviour
{
if(state!= FishState.Alive)
return;
controller.Speed = Data.Speed/GameManager.Ins.fishSpawner.fishSpeed;
if(controller!=null)
controller.Speed = Data.Speed/GameManager.Ins.fishSpawner.fishSpeed;
}
public void DieFish()
@@ -183,7 +232,8 @@ public class Fish : MonoBehaviour
state = FishState.Captured;
// 停止移动 & 碰撞
controller.enabled = false;
if(controller!=null)
controller.enabled = false;
if (collider)
collider.enabled = false;

View File

@@ -1,7 +1,9 @@
using System.Collections;
using System.Collections.Generic;
using DragonLi.Core;
using UnityEngine;
using FluffyUnderware.Curvy;
using Unity.VisualScripting;
public class FishSpawner : MonoBehaviour
{
@@ -16,6 +18,7 @@ public class FishSpawner : MonoBehaviour
public GameObject fishGroupPrefab;
public float fishSpeed;
public int maxFishCount;
private Dictionary<FishType, FishData> fishDataMap = new();
private Dictionary<FishType, FishSpawnState> spawnStates = new();
@@ -52,6 +55,7 @@ public class FishSpawner : MonoBehaviour
void Start()
{
fishSpeed = 1;
maxFishCount = 200;
}
void Update()
@@ -77,6 +81,8 @@ public class FishSpawner : MonoBehaviour
void TrySpawnFish()
{
if(AliveFishes.Count>=maxFishCount)
return;
FishData data = GetFishByProbability();
if (data == null) return;
@@ -180,6 +186,12 @@ public class FishSpawner : MonoBehaviour
FishData data= fishDataMap[fishType];
CurvySpline spline = GetSplineByType();
SpawnSingleFish(data,spline);
FishValueLevel level = FishValueHelper.GetValueLevel(data);
if (level == FishValueLevel.High)
highFishAlive = true;
if (level == FishValueLevel.UltraHigh)
angelHorseAlive = true;
}
#endregion
@@ -270,11 +282,19 @@ public class FishSpawner : MonoBehaviour
}, curTime);
}
public void GetAllFishes()
public IEnumerator GetAllFishes()
{
List<Fish> allFish = new List<Fish>();
foreach (var item in AliveFishes)
{
item.DieFish();
allFish.Add(item);
}
foreach (var fish in allFish)
{
fish.DieFish();
yield return new WaitForSeconds(0.01f);
}
}

View File

@@ -0,0 +1,190 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DragonLi.Core;
using UnityEngine;
public class SharkFish : Fish
{
[Header("鲨鱼设置")]
[NonSerialized]
public float patrolRadius = 8f; // 巡逻半径
[NonSerialized]
public float patrolSpeed = 0.5f; // 巡逻速度
[NonSerialized]
public float attackSpeed = 4f; // 攻击速度
[NonSerialized]
public float attackInterval = 10f; // 攻击间隔
[Header("攻击设置")]
public float attackDistance = 1.5f; // 攻击距离
public float retreatDistance = 5f; // 撤退距离
public Animator animator;
private Transform player;
private SharkState currentState;
private float attackTimer;
private int showTime;
private float curShowTime;
private Vector3 circleCenter;
// 鲨鱼状态枚举
private enum SharkState
{
Patrolling, // 圆形巡逻
Attacking, // 攻击玩家
Retreating // 撤退
}
void Start()
{
player = GameManager.Ins.player.transform;
currentState = SharkState.Patrolling;
attackTimer = attackInterval;
circleCenter = player.position;
showTime = 60;
StartCoroutine(SharkAI());
}
IEnumerator SharkAI()
{
while (curShowTime <= showTime|| state !=FishState.Alive)
{
switch (currentState)
{
case SharkState.Patrolling:
animator.SetInteger("state",0);
yield return StartCoroutine(PatrolBehavior());
break;
case SharkState.Attacking:
animator.SetInteger("state",1);
yield return StartCoroutine(AttackBehavior());
break;
case SharkState.Retreating:
animator.SetInteger("state",0);
yield return StartCoroutine(RetreatBehavior());
break;
}
curShowTime += Time.deltaTime;
yield return new WaitForEndOfFrame(); // 关键:等待一帧
}
OnSplineEnd();
}
// 圆形巡逻行为
IEnumerator PatrolBehavior()
{
float angle = 0f;
while (attackTimer > 0 && currentState == SharkState.Patrolling)
{
attackTimer -= Time.deltaTime;
// 更新圆形中心点为玩家当前位置
circleCenter = player.position;
// 圆形运动
angle += patrolSpeed * Time.deltaTime;
Vector3 targetPosition = circleCenter + new Vector3(
Mathf.Cos(angle) * patrolRadius,
0,
Mathf.Sin(angle) * patrolRadius
);
// 计算移动方向(前进方向)
Vector3 moveDirection = (targetPosition - transform.position).normalized;
// 如果移动方向不为零,让鲨鱼面向前进方向
if (moveDirection != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 5f * Time.deltaTime);
}
// 平滑移动到目标位置
transform.position = Vector3.Lerp(transform.position, targetPosition, 2f * Time.deltaTime);
yield return null;
}
if (attackTimer <= 0)
{
currentState = SharkState.Attacking;
attackTimer = attackInterval; // 重置计时器
}
}
// 攻击行为
IEnumerator AttackBehavior()
{
Vector3 attackDirection = (player.position - transform.position).normalized;
float attackStartTime = Time.time;
float maxAttackDuration = 3f;
while (currentState == SharkState.Attacking)
{
// 朝向玩家
transform.rotation = Quaternion.LookRotation(attackDirection);
// 冲向玩家
transform.position += attackDirection * attackSpeed * Time.deltaTime;
GameManager.Ins.PlaySound3D("鲨鱼袭击",transform,true);
// 检查是否到达攻击距离
float distanceToPlayer = Vector3.Distance(transform.position, player.position);
if (distanceToPlayer <= attackDistance)
{
// 攻击玩家
AttackPlayer();
currentState = SharkState.Retreating;
break;
}
// 防止攻击时间过长
if (Time.time - attackStartTime > maxAttackDuration)
{
currentState = SharkState.Retreating;
break;
}
yield return null;
}
}
// 撤退行为
IEnumerator RetreatBehavior()
{
Vector3 retreatDirection = (transform.position - player.position).normalized;
float retreatStartTime = Time.time;
float retreatDuration = 2f;
while (Time.time - retreatStartTime < retreatDuration && currentState == SharkState.Retreating)
{
// 远离玩家撤退
transform.position += retreatDirection * patrolSpeed * Time.deltaTime;
yield return null;
}
// 回到巡逻状态
currentState = SharkState.Patrolling;
}
// 攻击玩家
void AttackPlayer()
{
// 触发屏幕特效
EventDispatcher.TriggerEvent("PlayerHit",0);
}
void OnDrawGizmosSelected()
{
// 绘制巡逻范围
Gizmos.color = Color.blue;
Gizmos.DrawWireSphere(circleCenter, patrolRadius);
// 绘制攻击距离
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, attackDistance);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2c98c988603620a46a813ef97904a0db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,5 +1,6 @@
using UnityEngine;
using System.Collections;
using DG.Tweening;
public class Coin : MonoBehaviour
{
@@ -14,10 +15,34 @@ public class Coin : MonoBehaviour
private Vector3 startPos;
private int coinValue = 1;
[SerializeField] private float rotationDuration = 2f; // 旋转一圈的时间
[SerializeField] private RotateMode rotateMode = RotateMode.FastBeyond360; // 旋转模式
[SerializeField] private Ease easeType = Ease.Linear; // 旋转曲线
public void SetValue(int value)
{
coinValue = value;
StartRotation();
}
private void StartRotation()
{
// 获取当前旋转角度
Vector3 currentRotation = transform.eulerAngles;
// 设置目标角度Y轴增加360度
Vector3 targetRotation = new Vector3(
currentRotation.x,
currentRotation.y + 360f,
currentRotation.z
);
// 执行旋转动画
transform.DORotate(targetRotation, rotationDuration, rotateMode)
.SetEase(easeType)
.SetLoops(-1, LoopType.Restart) // -1 表示无限循环
.SetRelative(true); // 使用相对旋转
}
public void ExplodeTo(Vector3 targetPos, float force)

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fireworks : MonoBehaviour
{
public float playTime = 2;
public float curTime = 0;
private void Start()
{
}
private void Update()
{
curTime+= Time.deltaTime;
if (curTime >= playTime)
{
GameManager.Ins.PlaySound3D("烟花音效",transform,true);
curTime = 0;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6ce898bafe9d8454c96223b4b6864fea
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
public enum ItemType
{
RedEnvelope,//红包
Ingot,//元宝
}
public class Item : MonoBehaviour
{
public ItemType itemType;
public Collider collider;
private Vector3 velocity;
private bool flying;
private Transform target;
private float flyDuration;
private float shrinkStartDistance;
private float timer;
private Vector3 startPos;
private int coinValue = 1;
[SerializeField] private float rotationDuration = 2f; // 旋转一圈的时间
[SerializeField] private RotateMode rotateMode = RotateMode.FastBeyond360; // 旋转模式
[SerializeField] private Ease easeType = Ease.Linear; // 旋转曲线
private void Start()
{
switch (itemType)
{
case ItemType.RedEnvelope:
coinValue = 100;
break;
case ItemType.Ingot:
coinValue = 1000;
break;
}
transform.position+=Vector3.up*5;
collider = GetComponent<Collider>();
collider.enabled = false;
transform.DOMoveY(0, 3f).OnComplete(() =>
{
startPos = transform.position;
collider.enabled = true;
StartRotation();
});
}
private void StartRotation()
{
// 获取当前旋转角度
Vector3 currentRotation = transform.eulerAngles;
// 设置目标角度Y轴增加360度
Vector3 targetRotation = new Vector3(
currentRotation.x,
currentRotation.y + 360f,
currentRotation.z
);
// 执行旋转动画
transform.DORotate(targetRotation, rotationDuration, rotateMode)
.SetEase(easeType)
.SetLoops(-1, LoopType.Restart) // -1 表示无限循环
.SetRelative(true); // 使用相对旋转
}
void Update()
{
if (!flying || target == null) return;
timer += Time.deltaTime;
float t = Mathf.Clamp01(timer / flyDuration);
t = Mathf.SmoothStep(0, 1, t);
// 🌟 流线插值(略带弯曲)
Vector3 mid = (startPos + target.position) * 0.5f + Vector3.right * 0.3f;
Vector3 pos = Bezier(startPos, mid, target.position, t);
transform.position = pos;
float dist = Vector3.Distance(pos, target.position);
// 🌟 接近目标开始缩小
if (dist < shrinkStartDistance)
{
float scale = dist / shrinkStartDistance;
transform.localScale = Vector3.one * scale;
}
if (t >= 1f)
{
Collect();
}
}
void Collect()
{
GameInit.Ins.self.AddCoin(coinValue);
Destroy(gameObject);
}
Vector3 Bezier(Vector3 a, Vector3 b, Vector3 c, float t)
{
return Vector3.Lerp(
Vector3.Lerp(a, b, t),
Vector3.Lerp(b, c, t),
t
);
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
flying = true;
target = GameInit.Ins.self.RightHand;
GameManager.Ins.PlaySound2D("拾取音效");
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f9f0319e9428c78418f19b71be393e84
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using DragonLi.Core;
using IngameDebugConsole;
using TMPro;
using UnityEngine;
@@ -14,30 +15,45 @@ public class Shop : MonoBehaviour
public ShopItem[] shopItems;
public TMP_Text playerCoinText;
public TMP_Text tipText;
public GameObject[] tipObjs;
public EventSystemHandler eventSystem;
private int currentShowCoin;
private Tween coinTween;
private void Awake()
{
eventSystem.embeddedEventSystem=GameInit.Ins.eventSystem.gameObject;
}
private void Start()
{
shopUI.transform.localScale = Vector3.zero;
tipUI.transform.localScale = Vector3.zero;
foreach (var item in tipObjs)
{
item.transform.localScale = Vector3.zero;
}
for (int i = 0; i < shopItems.Length; i++)
{
shopItems[i].Init(GameManager.Ins.ShopDataDic[i + 1]);
}
foreach (GameObject item in tipObjs)
{
item.transform.localScale = Vector3.zero;
}
currentShowCoin = GameInit.Ins.self.GetCoinCount();
UpdateCoinText(currentShowCoin);
EventDispatcher.AddEventListener<int>("RefreshPlayerCoin", RefreshPlayerCoin);
EventDispatcher.AddEventListener<string>("ShowTip", ShowTip);
EventDispatcher.AddEventListener<int>("ShowTip", ShowTip);
}
public void ShowShopUI()
{
shopUI.transform.DOScale(0.01f, 0.5f).SetEase(Ease.OutBounce);
shopUI.transform.DOScale(0.007f, 0.5f).SetEase(Ease.OutBounce);
GameInit.Ins.self.UserHand();
}
@@ -47,14 +63,14 @@ public class Shop : MonoBehaviour
GameInit.Ins.self.UserGun();
}
public void ShowTipUI()
public void ShowTipUI(int tipId)
{
shopUI.transform.DOScale(1f, 0.5f).SetEase(Ease.OutBounce);
tipObjs[tipId].transform.DOScale(1f, 0.5f).SetEase(Ease.OutBounce);
}
public void HideTipUI()
public void HideTipUI(int tipId)
{
shopUI.transform.DOScale(0f, 0.5f).SetEase(Ease.OutBounce);
tipObjs[tipId].transform.DOScale(0f, 0.5f).SetEase(Ease.OutBounce);
}
private void OnTriggerEnter(Collider other)
{
@@ -92,19 +108,24 @@ public class Shop : MonoBehaviour
.SetEase(Ease.OutCubic);
}
public void ShowTip(string tip)
public void ShowTip(int tipId)
{
tipText.text = tip;
ShowTipUI();
ShowTipUI(tipId);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
HideTipUI();
HideTipUI(tipId);
}, 2f);
}
void UpdateCoinText(int coin)
{
playerCoinText.text = $"玩家当前金币:{coin}";
playerCoinText.text = coin.ToString();
}
public void CheckGunBtn(int id)
{
foreach (var item in shopItems)
{
item.CheckGunBuyBtn(id);
}
}
}

View File

@@ -12,7 +12,7 @@ public class ShopItem : MonoBehaviour
public TMP_Text coinTxt;
public Image coolingImage;
public Button buyBtn;
//public GameObject tip;
public Shop shop;
private int _itemCount;
private ShopData _data;
@@ -27,25 +27,36 @@ public class ShopItem : MonoBehaviour
{
_data = data;
nameTxt.text = data.Name;
coinTxt.text = data.Coin + "金币";
coinTxt.text = data.Coin.ToString();
coolingImage.gameObject.SetActive(false);
_itemCount = data.Count;
}
public void CheckGunBuyBtn(int id)
{
if (id > _data.Id)
{
coolingImage.gameObject.SetActive(true);
buyBtn.interactable = false;
}
}
public void OnBuyBtn()
{
if (GameInit.Ins.self.GetCoinCount() < _data.Coin)
{
ShowTip();
ShowTip(0);
return;
}
if(_itemCount>0)
_itemCount--;
UserItem();
buyBtn.gameObject.SetActive(false);
if (_itemCount == 0)
{
coolingImage.gameObject.SetActive(true);
ShowTip(1);
buyBtn.gameObject.SetActive(true);
buyBtn.interactable = false;
return;
}
if (_data.Time > 0)
@@ -54,9 +65,9 @@ public class ShopItem : MonoBehaviour
}
}
public void ShowTip()
public void ShowTip(int tipId)
{
EventDispatcher.TriggerEvent("RefreshPlayerCoin","金币不足");
EventDispatcher.TriggerEvent("ShowTip",tipId);
}
public void UserItem()
@@ -66,40 +77,53 @@ public class ShopItem : MonoBehaviour
{
case 1:
GameInit.Ins.self.Upgrade(2);
shop.CheckGunBtn(_data.Id);
break;
case 2:
GameInit.Ins.self.Upgrade(3);
shop.CheckGunBtn(_data.Id);
break;
case 3:
GameInit.Ins.self.Upgrade(4);
shop.CheckGunBtn(_data.Id);
break;
case 4:
GameInit.Ins.self.Upgrade(4);
GameInit.Ins.self.Upgrade(5);
shop.CheckGunBtn(_data.Id);
break;
case 5:
if (GameManager.Ins.fishSpawner.GetFishCount(FishType.Shark) > 0)
{
EventDispatcher.TriggerEvent("RefreshPlayerCoin","空中已经有一条鲨鱼,请先消灭它");
break;
EventDispatcher.TriggerEvent("ShowTip","空中已经有一条鲨鱼,请先消灭它");
Debug.LogError("空中已经有一条鲨鱼,请先消灭它");
}
GameManager.Ins.fishSpawner.CreateTypeFish(FishType.Shark);
else
{
GameManager.Ins.fishSpawner.CreateTypeFish(FishType.Shark);
}
break;
case 6:
if (GameManager.Ins.fishSpawner.GetFishCount(FishType.AngelHorse) > 0)
{
EventDispatcher.TriggerEvent("RefreshPlayerCoin","空中已经有一只金马,请先消灭它");
break;
EventDispatcher.TriggerEvent("ShowTip","空中已经有一只金马,请先消灭它");
Debug.LogError("空中已经有一只金马,请先消灭它");
}
else
{
GameManager.Ins.fishSpawner.CreateTypeFish(FishType.AngelHorse);
}
GameManager.Ins.fishSpawner.CreateTypeFish(FishType.AngelHorse);
break;
case 7:
GameManager.Ins.fishSpawner.SetFishSpeed(_data.Time);
GameManager.Ins.PlaySound2D("冻结");
break;
case 8:
GameInit.Ins.self.SetGetCoinIndex(_data.Time);
GameManager.Ins.PlaySound2D("双倍掉落");
break;
case 9:
GameManager.Ins.fishSpawner.GetAllFishes();
StartCoroutine(GameManager.Ins.fishSpawner.GetAllFishes());
break;
}
}
@@ -107,13 +131,13 @@ public class ShopItem : MonoBehaviour
IEnumerator StartCooling()
{
float timer = 0f;
while (timer>=_data.Time)
coolingImage.gameObject.SetActive(true);
while (timer<_data.Time)
{
coolingImage.fillAmount =(1- timer / _data.Time);
timer += Time.deltaTime;
yield return new WaitForEndOfFrame(); // 关键:等待一帧
}
buyBtn.gameObject.SetActive(true);
coolingImage.fillAmount = 1;
coolingImage.gameObject.SetActive(false);
if ((_data.Id == 5 || _data.Id == 6)&& GameManager.Ins.fishSpawner.GetFishCount((FishType)_data.Id)>0)

View File

@@ -6,9 +6,11 @@ using System.Collections.Generic;
using System.Net.WebSockets;
using DarkTonic.MasterAudio;
using FluffyUnderware.Curvy;
using Pathfinding;
using TMPro;
using TruegearSdk;
using Unity.XR.PXR;
using UnityEngine.EventSystems;
using UnityEngine.XR.Interaction.Toolkit;
using Random = UnityEngine.Random;
@@ -20,11 +22,17 @@ public class GameInit : MonoBehaviour
public Transform leftHand;
public Transform rightHand;
public TruegearAndroidConnector androidConnector;
public AstarPath aiPath;
public Transform showPos;
public CurvySpline[] curvySplines;
public CurvySpline surroundSpline;
public EventSystem eventSystem;
[NonSerialized]
public GameObject HitUI;

View File

@@ -4,6 +4,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using DarkTonic.MasterAudio;
using Pathfinding;
using Unity.Mathematics;
using Unity.XR.PXR;
using UnityEngine;
@@ -143,6 +144,11 @@ public class GameManager : MonoBehaviour
[Header("道具")]
public GameObject gameStartPointPre;
public GameObject fireworksPre;
public GameObject redEnvelopePre;//红包
public GameObject ingotPre;//元宝
public GameObject shopPre;
public GameObject coinPilePre;
@@ -166,14 +172,9 @@ public class GameManager : MonoBehaviour
public float curTime;
public float buffAtk = 0f;
public float buffDef = 0f;
public LoginInfo authInfo = new LoginInfo();
public Enemy curBoss;
public int curLevel = 0;
public List<GameObject> itemList = new List<GameObject>();
//添加
[Header("AI角色")]
@@ -190,10 +191,8 @@ public class GameManager : MonoBehaviour
#if !UNITY_EDITOR
PXR_Enterprise.InitEnterpriseService();
PXR_Enterprise.BindEnterpriseService();
TrueGearEffectManager.Ins.StartRequestTrueGear();
#endif
CoroutineTaskManager.Instance.WaitSecondTodo(ShowPlayerUI, 1.5f);
}
/// <summary>
@@ -343,7 +342,7 @@ public class GameManager : MonoBehaviour
// CoroutineTaskManager.Instance.WaitSecondTodo(() =>
// AudioManager.Ins?.SoundPlay("2.39BGM", true), 30f);
isGamePlay = true;
CreateShowPre();
CreateShopPre();
}
//修改处添加AI介绍完成后的游戏开始方法
@@ -445,6 +444,12 @@ public class GameManager : MonoBehaviour
}, 5f);
}
public void CreateFireworks(Vector3 pos)
{
GameObject point = Instantiate(fireworksPre);
point.transform.position = pos;
}
public void CreatePlayer()
{
player = Instantiate(playerPre);
@@ -456,10 +461,54 @@ public class GameManager : MonoBehaviour
rightHand = hand.GetComponent<RightHand>();
}
public void CreateShowPre()
public void CreateShopPre()
{
GameObject point = Instantiate(shopPre);
point.transform.position = GameInit.Ins.showPos.position;
point.transform.rotation = GameInit.Ins.showPos.rotation;
}
public void CreateItemPre()
{
if (itemList.Count >= 10)
{
Destroy(itemList[0]);
itemList.RemoveAt(0);
}
int randIndex=Random.Range(0,100);
List<GraphNode> walkableNodes = GetAllWalkableNodes();
GraphNode randomNode = walkableNodes[Random.Range(0, walkableNodes.Count)];
Vector3 spawnPosition = (Vector3)randomNode.position;
if (randIndex >= 10)
{
var obj= Instantiate(redEnvelopePre,spawnPosition,Quaternion.identity);
itemList.Add(obj);
}
else
{
var obj=Instantiate(ingotPre,spawnPosition,Quaternion.identity);
itemList.Add(obj);
}
}
List<GraphNode> GetAllWalkableNodes()
{
List<GraphNode> walkableNodes = new List<GraphNode>();
foreach (NavGraph graph in AstarPath.active.graphs)
{
graph.GetNodes(node =>
{
if (node != null && node.Walkable)
{
walkableNodes.Add(node);
}
return true;
});
}
Debug.Log($"找到 {walkableNodes.Count} 个可行走节点");
return walkableNodes;
}
public void WinEndGame()
@@ -481,41 +530,33 @@ public class GameManager : MonoBehaviour
Destroy(aiCharacter);
}
}
public void LoseEndGame(bool isWin)
{
ShowEndGameUI(isWin);
if (curBoss != null)
{
curBoss.Dead();
}
GameInit.Ins.self.IsAlive = false;
GameInit.Ins.self.End();
isGameEnd = true;
//CurEnemyDie();
AudioManager.Ins.SoundPlay(6, true);
AudioManager.Ins.StopLoop();
//修改处销毁AI角色
if (aiCharacter != null)
{
//取消注册事件
AIController aiController = aiCharacter.GetComponent<AIController>();
if (aiController != null)
{
aiController.OnIntroductionComplete -= StartGameAfterIntroduction;
}
Destroy(aiCharacter);
}
}
private float _createItemInterval=5;
private float curCreateItemTime;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
curBoss.Dead();
GameInit.Ins.self.AddCoin(5000);
}
if (fishSpawner.GetFishCount(FishType.AngelHorse) >= 1)
{
curCreateItemTime+=Time.deltaTime;
if (curCreateItemTime >= _createItemInterval)
{
CreateItemPre();
curCreateItemTime=0;
}
}
}
public void ClearItem()
{
foreach (var item in itemList)
{
Destroy(item);
}
itemList.Clear();
}
public void PlaySound2D(string soundName)

View File

@@ -1,12 +1,18 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DragonLi.Core;
using UnityEngine;
public class LookPlayer : MonoBehaviour
{
private void OnEnable()
{
transform.LookAt(GameManager.Ins.player.transform);
}
private void Update()
{
transform.LookAt(GameManager.Ins.player.transform.position.ReflectVectorXOZ());
}
}

View File

@@ -68,6 +68,7 @@ public class Player : MonoBehaviour
#endif
currentHp = maxHp;
GameInit.Ins.self = this;
GetCoinIndex = 1;
EventDispatcher.TriggerEvent("GetHand", LeftHand, RightHand);
}
@@ -106,7 +107,7 @@ public class Player : MonoBehaviour
public float OnReceiveDamage(float damage, object info, Transform _sender)
{
return 0;
float curDamage = (GameManager.Ins.buffDef > 0) ? (damage / GameManager.Ins.buffDef) : damage;
float curDamage = damage;
SetBlood(-curDamage);
#if !UNITY_EDITOR && UNITY_ANDROID && PICO
if (_sender != null)
@@ -260,12 +261,12 @@ public class Player : MonoBehaviour
public void UserHand()
{
GameManager.Ins.rightHand.Show();
playerHands.gameObject.SetActive(false);
playerHands.gunPent.SetActive(false);
}
public void UserGun()
{
playerHands.gameObject.SetActive(true);
playerHands.gunPent.SetActive(true);
playerHands.RefreshGun(GunId);
GameManager.Ins.rightHand.Hide();
}

View File

@@ -60,7 +60,7 @@ public class PlayerBullet : MonoBehaviour
if(GameManager.Ins.PlayerBulletDataDic.Count>0)
_damages = GameManager.Ins.PlayerBulletDataDic[(int)bulletType].Damage;
int randomDamage = Random.Range(_damages[0], _damages[1]);
randomDamage += (Mathf.FloorToInt(GameManager.Ins.buffAtk * randomDamage));
randomDamage += (Mathf.FloorToInt( randomDamage));
isCriticalHit=randomDamage > (_damages[1] - (_damages[1] - _damages[0]) * 0.35f);
return randomDamage;
}

View File

@@ -18,6 +18,9 @@ public class PlayerHands : MonoBehaviour
public int[] Indices; // 可选UI 圆环选择器索引
public WeaponSelector weaponSelector; // 可选UI 武器选择器事件源
public GameObject gunPent;
[SerializeField] private Player player; // 用于后坐力回调
private IWeapon[] weapons; // 缓存的 IWeapon 组件

View File

@@ -35,7 +35,7 @@ public class RightHand : MonoBehaviour
private void Update()
{
transform.position = GameInit.Ins.rightHand.position;
transform.rotation = GameInit.Ins.rightHand.rotation;
transform.position = GameInit.Ins.self.RightHand.position;
transform.rotation = GameInit.Ins.self.RightHand.rotation;
}
}

View File

@@ -1,9 +1,11 @@
using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using UnityEngine;
[Serializable]
@@ -41,13 +43,9 @@ public class HttpServer : MonoBehaviour
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void Start()
{
StartServer();
Task.Run(StartServer);
}
#region HTTP Server
@@ -56,15 +54,11 @@ public class HttpServer : MonoBehaviour
try
{
listener = new HttpListener();
listener.Prefixes.Add(SERVER_URL);
listener.Prefixes.Add($"http://{GetLocalIP()}:12345/");
listener.Start();
isRunning = true;
serverThread = new Thread(ListenLoop)
{
IsBackground = true
};
serverThread.Start();
ListenLoop();
Debug.Log($"✅ HTTP Server 启动成功:{SERVER_URL}");
}
@@ -73,7 +67,17 @@ public class HttpServer : MonoBehaviour
Debug.LogError("❌ HTTP Server 启动失败:" + e);
}
}
private string GetLocalIP()
{
var host = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
foreach (var ip in host.AddressList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
return ip.ToString();
}
return "127.0.0.1";
}
private void ListenLoop()
{
while (isRunning && listener.IsListening)
@@ -146,6 +150,7 @@ public class HttpServer : MonoBehaviour
};
string json = JsonUtility.ToJson(resp);
Debug.LogError("数据:"+json);
byte[] data = Encoding.UTF8.GetBytes(json);
response.OutputStream.Write(data, 0, data.Length);
}

View File

@@ -8,161 +8,80 @@ using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using Random = UnityEngine.Random;
public class PlayerUI : MonoBehaviour
{
public GameObject hitEffect;
public TMP_Text timeTxt;
[NonSerialized]
public float second=60*15f;
public GameObject[] teachUIs;
public Image dieImage;
public Sprite[] dieTimeSprite;
public GameObject dieUI;
public TextMeshProUGUI bulletAmount;
private bool IsAlive = true;
public RectTransform[] hits;
public float fadeInDuration = 1.0f;
private CanvasGroup canvasGroup;
public Image blood1;
public Image blood2;
public TMP_Text hpTxt;
private int currentIndex = 0; // 当前对话索引
private string[] dialogueTexts; // 存储对话文本的数组
public void Awake()
{
GameInit.Ins.HitUI = hitEffect;
GameInit.Ins.DieUI = dieUI;
second = GameInit.Ins.gameTime;
}
void Start()
{
EventDispatcher.AddEventListener<float, float>("HpChange", HpChange);
EventDispatcher.AddEventListener<Transform>("PlayerDeath", PlayerDeath);
EventDispatcher.AddEventListener<Transform>("PlayerAlive", PlayerAlive);
//EventDispatcher.AddEventListener<int>("PromptMessage", ShowMessage);
EventDispatcher.AddEventListener<int, float>("ShowTeachUI", ShowTeachUI);
EventDispatcher.AddEventListener<int>("ShowBulletAmount", ShowBulletAmount);
EventDispatcher.AddEventListener<int>("PlayerHit", ShowEx);
canvasGroup = GetComponent<CanvasGroup>();
// 设置初始透明度为0
canvasGroup.alpha = 0f;
// 使用DoTween实现透明度从0到1的渐显效果
canvasGroup.DOFade(1f, fadeInDuration);
hpTxt.text = 100 + "%";
}
public void ShowBulletAmount(int amount)
{
if (amount == 0)
foreach (var item in hits)
{
bulletAmount.text = "";
}
else
{
if (amount > 1000)
{
bulletAmount.text = "无限";
return;
}
bulletAmount.text = amount.ToString();
}
}
public void PlayerDeath(Transform transform)
{
IsAlive = false;
StartCoroutine(StartCountdown());
}
IEnumerator StartCountdown()
{
foreach (var item in dieTimeSprite)
{
dieImage.sprite = item;
yield return new WaitForSeconds(1.0f);
item.gameObject.SetActive(false);
}
}
public void PlayerAlive(Transform transform)
{
IsAlive = true;
}
public void HpChange(float currentHp, float maxHp)
{
blood2.fillAmount = currentHp / maxHp;
DOTween.To(() => blood1.fillAmount, x => blood1.fillAmount = x, currentHp / maxHp, 0.5f);//血量变化
hpTxt.text = Mathf.FloorToInt((currentHp/maxHp)*100) + "%";
if (Mathf.FloorToInt((currentHp / maxHp) * 100) < 0)
hpTxt.text = 0+"%";
}
// public void ShowMessage(int index)
// {
// switch (index)
// {
// case 0:
// Step("扣动扳机键开始射击!", 0, 2.0f, "1.3");
// ShowTeachUI(0, 0);
// ShowTeachUI(1, 2.0f);
// ShowTeachUI(2, 4.0f);
// MonoSingleton<CoroutineTaskManager>.Instance.WaitSecondTodo(() =>
// {
// Step("勇士,快消灭传送门!", 0, 2.0f, "1.1");
// },3f);
// break;
// case 1:
// Step("太好了,你们收集到了能源魔方!", 0, 2.0f, "1.9");
// break;
// }
// }
//显示消息,按间隔消失
// private void Step(string text, float wait, float time, string clipName,Transform tran=null)
// {
// if(tran == null)
// tran=GameInit.Ins.self.transform;
// CoroutineTaskManager.Instance.WaitSecondTodo(() =>
// {
// info.gameObject.SetActive(true);
// info.text = text;
// GameInit.Ins.PlayAudio(clipName,tran,true);
// CoroutineTaskManager.Instance.WaitSecondTodo(() =>
// {
// info.gameObject.SetActive(false);
// }, time);
// }, wait);
// }
//显示教学UI
public void ShowTeachUI(int index, float wait)
public void ShowEx(int txId)
{
if (hits == null || txId < 0 || txId >= hits.Length || hits[txId] == null)
{
Debug.LogError("特效索引无效或数组为空");
return;
}
// 激活特效
hits[txId].gameObject.SetActive(true);
GameManager.Ins.PlaySound2D("啃咬");
// 获取画布中心坐标
Vector3 canvasCenter = new Vector3(Screen.width * 0.5f, Screen.height * 0.5f, 0f);
// 简单偏移:上下左右随机方向偏移固定距离
Vector3 randomOffset = GetSimpleOffset();
// 设置UI位置
hits[txId].localPosition = randomOffset;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
teachUIs[index].SetActive(true);
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
if (hits[txId] != null)
{
teachUIs[index].SetActive(false);
}, 2.0f);
}, wait);
hits[txId].gameObject.SetActive(false);
}
}, 2f);
}
// 简单偏移:上下左右四个方向随机偏移
// 固定偏移量
private Vector3 GetSimpleOffset()
{
// 固定偏移200像素
float offset = 200f;
float offsetX = Random.Range(-offset, offset);
float offsetY = Random.Range(-100, offset);
return new Vector3(offsetX, offsetY, 0);
}
private void Update()
@@ -188,7 +107,6 @@ public class PlayerUI : MonoBehaviour
else
{
GameManager.Ins.curTime = second;
GameManager.Ins.LoseEndGame(false);
timeTxt.text = "00:00";
}
}