| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using Sirenix.OdinInspector;
- using UnityEngine.Events;
- public class BlackUmbrella : MonoBehaviour
- {
- public enum UmbrellaState
- {
- none,
- appear, //出现,原地动画
- sprint, //飞出去
- stay, //停在目标点
- back, //收回
- disappear, //消失前原地动画
- }
- [DisplayOnly]
- public UmbrellaState umbrellaState; //当前黑伞的状态
- [HideInInspector]
- public Transform umbrellaOrigPos;
- private Vector3 origPos;
- [HideInInspector]
- public Transform umbrellaBackPos;
- public Transform owner;
- WaterSprite ws;
- private Animator ani;
- private WaterSpriteAttackController attackCon;
- //玩家
- private PlayerController pc;
- //黑伞的目标坐标
- public float farFromPlayerDis;
- private Vector3 aimPos;
- private float attackDis;
- //黑伞攻击次数
- public int minTime, maxTime;
- private int allTime;
- //黑伞的攻击
- private float umbrePastTime;
- [LabelText("黑伞初速度")]
- public float initialSpeed;
- [LabelText("黑伞出现时长")]
- public float appearTime;
- [LabelText("黑伞停留时长")]
- public float stayTime;
- [LabelText("黑伞收回时长")]
- public float backTime;
- private bool hasBackAni;
- [LabelText("黑伞消失时长")]
- public float disappearTime;
- [LabelText("黑伞位置提示特效")]
- public GameObject effect;
- private GameObject effectIns;
- //提示X坐标
- public float leftX, rightX;
- //是第一次攻击,则无需索敌
- private bool isFirst;
- public UnityAction OnBack;
- private void Start()
- {
- if (ani == null)
- {
- ani = GetComponent<Animator>();
- ws = owner.GetComponent<WaterSprite>();
- GetComponentInChildren<AttackTrigger>().owner = ws;
- attackCon = owner.GetComponent<WaterSpriteAttackController>();
- pc = PlayersInput.instance[0];
- }
- }
- //放出这个攻击!
- public void Release()
- {
- allTime = Random.Range(minTime, maxTime);
- isFirst = true;
- ChangeUmbrellaState(UmbrellaState.appear);
- }
- public void ChangeUmbrellaState(UmbrellaState us)
- {
- if (umbrellaState == us)
- {
- return;
- }
- umbrellaState = us;
- switch (us)
- {
- case UmbrellaState.appear:
- transform.position = umbrellaOrigPos.position;
- gameObject.SetActive(true);
- break;
- case UmbrellaState.sprint:
- origPos = transform.position;
- aimPos = pc.transform.position;
- if (isFirst && aimPos.x < transform.position.x)
- {
- aimPos = transform.position + new Vector3(1, 0, 0) * farFromPlayerDis;
- attackDis = farFromPlayerDis;
- isFirst = false;
- }
- else
- {
- aimPos.y = origPos.y;
- int fx = 1;
- if (aimPos.x < origPos.x)
- {
- fx = -1;
- }
- aimPos.x += farFromPlayerDis * fx;
- attackDis = Mathf.Abs(aimPos.x - transform.position.x);
- }
- break;
- case UmbrellaState.stay:
- aimPos.y = pc.bodyTrans.position.y;
- break;
- case UmbrellaState.back:
- OnBack?.Invoke();
- break;
- case UmbrellaState.disappear:
- break;
- }
- }
- private void OnUmbrellaState()
- {
- umbrePastTime += Time.deltaTime;
- switch (umbrellaState)
- {
- case UmbrellaState.appear:
- if (umbrePastTime >= appearTime)
- {
- umbrePastTime = 0;
- ChangeUmbrellaState(UmbrellaState.sprint);
- }
- break;
- case UmbrellaState.sprint:
- float distanceCovered = umbrePastTime * initialSpeed;
- float fraction = distanceCovered / attackDis;
- float dec = 1 - (1 - fraction) * (1 - fraction);
- transform.position = Vector3.Lerp(origPos, aimPos, dec);
- if (Mathf.Abs(transform.position.x - aimPos.x) <= 0.2f)
- {
- transform.position = aimPos;
- umbrePastTime = 0;
- ChangeUmbrellaState(UmbrellaState.stay);
- }
- break;
- case UmbrellaState.stay:
- aimPos.y = pc.bodyTrans.position.y;
- transform.position = Vector3.MoveTowards(transform.position, aimPos, 9f * Time.deltaTime);
- if (umbrePastTime >= stayTime)
- {
- transform.position = aimPos;
- umbrePastTime = 0;
- allTime--;
- if (allTime > 0)
- {
- ChangeUmbrellaState(UmbrellaState.sprint);
- }
- else
- {
- ChangeUmbrellaState(UmbrellaState.back);
- }
- }
- break;
- case UmbrellaState.back:
- float t2 = Mathf.Clamp01(umbrePastTime / backTime);
- float smoothT2 = Mathf.SmoothStep(0, 1, t2);
- transform.position = Vector3.Lerp(aimPos, umbrellaBackPos.position, smoothT2);
- if (umbrePastTime >= backTime)
- {
- umbrePastTime = 0;
- hasBackAni = false;
- ws.isHoldingUmbre = true;
- ChangeUmbrellaState(UmbrellaState.disappear);
- }
- else if (!hasBackAni && umbrePastTime >= backTime - 0.6f)
- {
- hasBackAni = true;
- attackCon.isUmbrellaBack = true;
- ws.isHoldingUmbre = true;
- }
- break;
- case UmbrellaState.disappear:
- if (umbrePastTime >= disappearTime)
- {
- umbrePastTime = 0;
- ChangeUmbrellaState(UmbrellaState.none);
- gameObject.SetActive(false);
- }
- break;
- }
- }
- private bool IsTargetVisible(GameObject target)
- {
- Camera camera = Camera.main;
- // 获取物体在视口中的位置(归一化坐标)
- Vector3 viewportPoint = camera.WorldToViewportPoint(target.transform.position);
- // 检查坐标是否在屏幕范围内(0-1之间)
- bool inCameraView = viewportPoint.x >= 0 && viewportPoint.x <= 1 &&
- viewportPoint.y >= 0 && viewportPoint.y <= 1 &&
- viewportPoint.z > 0; // z>0 表示在相机前方
- return inCameraView;
- }
- private void ShowTip()
- {
- if (!effectIns)
- {
- effectIns = PoolManager.Instantiate(effect, Camera.main.transform);
- effectIns.GetComponent<Bullet>().owner = ws;
- }
- if (!IsTargetVisible(gameObject))
- {
- if (gameObject.transform.position.x > pc.transform.position.x)
- {
- effectIns.transform.localPosition = new Vector3(rightX, 0, 16);
- Vector3 pos = effectIns.transform.position;
- pos.y = gameObject.transform.position.y;
- effectIns.transform.position = pos;
- effectIns.transform.localEulerAngles = new Vector3(0.8f, 0.1f, 1);
- }
- else
- {
- effectIns.transform.localPosition = new Vector3(leftX, 0, 16);
- Vector3 pos = effectIns.transform.position;
- pos.y = gameObject.transform.position.y;
- effectIns.transform.position = pos;
- effectIns.transform.localEulerAngles = new Vector3(-0.8f, 0.1f, 1);
- }
- effectIns.SetActive(true);
- }
- else
- {
- effectIns.SetActive(false);
- }
- }
- private void Update()
- {
- OnUmbrellaState();
- ShowTip();
- }
- }
|