using asap.core; using cfg; using DG.Tweening; using Game; using GameCore; using System.Collections.Generic; using UnityEngine; using UnityEngine.AddressableAssets; public class CrossbowCameraMove : MonoBehaviour { Vector3 _curMousePos; Vector3 _offsetEuler; Quaternion targetRotation; //屏幕拖动比例 float dragCameraScale = 0.03f; private Vector3 initialRotation; bool isFinish; Transform handRoot; HandController HandController; GameObject handAB; Crossbow crossbow; CrossbowArrow crossbowArrow; AquariumCameraManager manager; int state = 0;//0:未开始 1:射击结束 2:收紧线 3:逃脱 Vector2 cameraOffset; public FishMovement guide; private void Awake() { crossbow = GetComponentInChildren(); crossbowArrow = GetComponentInChildren(); crossbowArrow.gameObject.SetActive(false); crossbow.fishingLineRenderer.enabled = false; crossbowPos = crossbow.animator.transform.localPosition; } public void Init(AquariumCameraManager aquariumCameraManager, Transform handRoot, Vector2 cameraOffset, FishMovement guide) { this.manager = aquariumCameraManager; this.cameraOffset = cameraOffset; this.handRoot = handRoot; this.guide = guide; LoadHand(); } public void LoadHand() { GloveData gloveData = GContext.container.Resolve().GetGloveData; InitRodHandAsync(gloveData); } async void InitRodHandAsync(GloveData gloveData) { string path = gloveData.Fbx; if (handAB != null) { Addressables.ReleaseInstance(handAB); } handAB = await Addressables.InstantiateAsync(gloveData.Fbx, handRoot).Task; if (handAB != null) { HandController = handAB.GetComponent(); if (crossbow != null) { HandController.SetHandTargets(crossbow.RightHandTargets, crossbow.LeftHandTargets, null); } } } public float CheckAngle(float value) { float angle = value - 180; if (angle > 0) return angle - 180; return angle + 180; } //收线音效 Sound soundLine; AudioClip lineAudio; async void PlaySoundLine(string audioName) { StopSoundLine(); lineAudio = await Addressables.LoadAssetAsync(audioName).Task; if (lineAudio) { soundLine = GContext.container.Resolve().GetNewFishingSound(lineAudio); soundLine.audioSource.Play(); soundLine.audioSource.loop = true; } } void StopSoundLine() { if (soundLine) { soundLine.audioSource.Stop(); soundLine.ReturnPool(); soundLine = null; } } public void TriggerCrossbow(string value) { crossbow.animator.SetBool("Aim", value == "Aim"); crossbow.animator.SetBool("Back", value == "Back"); crossbow.animator.SetBool("Shoot", value == "Shoot"); //crossbow.animator.SetTrigger(value); } public async void Shoot(float[] FxScale, Dictionary fx_hunt_prefab, bool isRob, float cameraToFishDis, float shootTime, FishMovement fish) { crossbow.animator.SetTrigger("Shoot"); Vector3 targetPos = fish.targetPos; manager.crossbowCamera.gameObject.SetActive(false); Vector3 cameraposition = manager.crossbowCamera.transform.position; float r = fish.AvoidRadius * cameraToFishDis; float t = 1 - r / (targetPos - cameraposition).magnitude; if (t < 0) { t = 0; } Vector3 newVector = Vector3.Lerp(cameraposition, targetPos, t); GContext.Publish(new EventFishingSound("audio_huntingfish_shoot")); crossbowArrow.gameObject.SetActive(true); crossbow.fishingLineRenderer.enabled = true; manager.cameraVirtual.gameObject.SetActive(false); var cameraParent = manager.followArrowCamera.transform.parent; //parent.position = manager.crossbowCamera.transform.position; await Awaiters.NextFrame; cameraParent.gameObject.SetActive(true); manager.followArrowCamera.transform.localPosition = new Vector3(0.25f, 0.25f, -0.25f); //cameraParent.position = manager.crossbowCamera.transform.position; cameraParent.DOMove(newVector, shootTime).SetEase(Ease.Linear); manager.followArrowCamera.LookAt = crossbowArrow.transform; PlaySoundLine("audio_huntingfish_airflow"); transform.rotation = Quaternion.LookRotation(targetPos - transform.position); crossbow.root.SetActive(false); handRoot.gameObject.SetActive(false); GameObject hunt_shoot_go = null; if (fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_shoot", out GameObject hunt_shoot)) { hunt_shoot_go = Instantiate(hunt_shoot, crossbowArrow.transform); } crossbowArrow.transform.DOMove(targetPos, shootTime).SetEase(Ease.Linear); await Awaiters.Seconds(shootTime); manager.followArrowCamera.LookAt = null; state = 1; AddLinePos(); crossbowArrow.animator.SetTrigger("Shoot"); if (hunt_shoot_go != null) { Destroy(hunt_shoot_go); } if (fish.fish != null) { int q = fish.slotData.aquariumFishID - 1; float fxScale = FxScale[q] / fish.transform.localScale.x; GameObject hunt_fishhitbig_go = null; GameObject hunt_fishhitsmall_go = null; GameObject hunt_fishhurt_go = null; Transform fishPos = isRob ? fish.fish.mouthPos : fish.fishPos; if (fish.fish.Root && fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_fishhitbig", out GameObject hunt_fishhitbig)) { hunt_fishhitbig_go = Instantiate(hunt_fishhitbig, fish.fish.Root); hunt_fishhitbig_go.transform.localScale = Vector3.one * fxScale; hunt_fishhitbig_go.transform.rotation = Quaternion.identity; } if (fishPos && fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_fishhitsmall", out GameObject hunt_fishhitsmall)) { hunt_fishhitsmall_go = Instantiate(hunt_fishhitsmall, fishPos); hunt_fishhitsmall_go.transform.localScale = Vector3.one * fxScale; hunt_fishhitsmall_go.transform.rotation = Quaternion.identity; } if (fishPos && fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_fishhurt", out GameObject hunt_fishhurt)) { hunt_fishhurt_go = Instantiate(hunt_fishhurt, fishPos); hunt_fishhurt_go.transform.localScale = Vector3.one * fxScale; } if (isRob) { GameObject hunt_capture_go = null; if (fish.fish.Root && fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_capture", out GameObject hunt_capture)) { hunt_capture_go = Instantiate(hunt_capture, fish.fish.Root); hunt_capture_go.transform.localScale = Vector3.one * fxScale; } } else { GameObject hunt_escape_go = null; if (fx_hunt_prefab.TryGetValue("fx_aquarium_hunt_escape", out GameObject hunt_escape)) { hunt_escape_go = Instantiate(hunt_escape, fish.fish.Root); hunt_escape_go.transform.localScale = Vector3.one * fxScale; } } crossbowArrow.transform.parent = fishPos; crossbowArrow.transform.localPosition = Vector3.zero; if (isRob) { GContext.Publish(new EventFishingSound("audio_huntingfish_hitbig")); } else { GContext.Publish(new EventFishingSound("audio_huntingfish_hitsmall")); } } StopSoundLine(); HideCrossbow(false); crossbow.animator.SetTrigger("Capture"); } Vector3 crossbowPos; public void HideCrossbow(bool isHide) { guide = null; if (isHide) { crossbowPos = crossbow.animator.transform.localPosition; crossbow.animator.transform.localPosition = Vector3.back * 100; } else { crossbow.animator.transform.localPosition = crossbowPos; } //handRoot.localPosition = isHide ? Vector3.back * 100 : new Vector3(0, 1, -0.5f); } List vector3s = new List(); float lineChengeTime = 1; public void Escape(float arrowEscapeTime) { GContext.Publish(new EventFishingSound("audio_huntingfish_escape")); manager.followArrowCamera.LookAt = null; HideCrossbow(false); crossbowArrow.animator.SetTrigger("Escape"); crossbow.animator.SetTrigger("Escape"); crossbowArrow.transform.parent = crossbow.transform.parent; crossbowArrow.transform.DOMoveY(-5, arrowEscapeTime).OnComplete(() => { state = 2; vector3s.Clear(); }); state = 1; AddLinePos(); } public void Target() { isFinish = true; } public float Capture(float fishToCameraDistance, float lineDrawMinTime, float cameraToFishDis, float lineDrawSpeed, FishMovement targetMovement) { manager.cameraVirtual.transform.DOKill(); manager.cameraVirtual.transform.localPosition = Vector3.zero; manager.followArrowCamera.transform.position = manager.cameraVirtual.transform.position; manager.followArrowCamera.transform.rotation = manager.cameraVirtual.transform.rotation; manager.followArrowCamera.LookAt = targetMovement.transform; crossbow.root.SetActive(true); handRoot.gameObject.SetActive(true); crossbowArrow.animator.SetTrigger("Capture"); PlaySoundLine("audio_huntingfish_capture"); state = 2; vector3s.Clear(); Vector3 vector3 = targetMovement.targetPos; Vector3 targetPos = crossbow.transform.position; float r = targetMovement.AvoidRadius * cameraToFishDis; float t = 1 - r / (targetPos - vector3).magnitude; if (t < 0) { t = 0; } Vector3 newVector = Vector3.Lerp(vector3, targetPos, t); newVector.z += fishToCameraDistance; var captureTime = (crossbowArrow.transform.position - newVector).magnitude / lineDrawSpeed; if (captureTime < lineDrawMinTime) { captureTime = lineDrawMinTime; } targetMovement.transform.DOMove(newVector, captureTime).SetEase(Ease.Linear) .OnComplete(() => crossbow.animator.SetTrigger("CaptureEnd")); return captureTime; } public void Captureed() { StopSoundLine(); crossbowArrow.transform.parent = crossbow.transform.parent; crossbowArrow.transform.DOMoveY(-10, 3) .OnComplete(() => crossbow.fishingLineRenderer.enabled = false); } async void AddLinePos() { float allTime = 1f; float time = allTime; float timeInterval = 0; vector3s.Clear(); float elapsedTime = 0.02f; while (time > 0) { elapsedTime = Time.deltaTime; timeInterval += elapsedTime; await Awaiters.Seconds(elapsedTime); time -= elapsedTime; ParabolaHarmonicSimulation parabolaHarmonicSimulation = new ParabolaHarmonicSimulation(); parabolaHarmonicSimulation.startPos = crossbowArrow.EndLine.position; parabolaHarmonicSimulation.starTime = timeInterval; parabolaHarmonicSimulation.curTime = timeInterval; parabolaHarmonicSimulation.allTime = allTime; vector3s.Add(parabolaHarmonicSimulation); } } Vector3 GetCurPos(ParabolaHarmonicSimulation data, out float zeroTime) { data.curTime += Time.deltaTime; float starTime = data.starTime; float curTime = data.curTime - starTime; //归0时间 zeroTime = curTime / data.allTime; Vector3 vector3 = (crossbow.TopLine.position + crossbowArrow.EndLine.position) / 2; if (zeroTime < 1) { Vector3 startPos = Vector3.Lerp(data.startPos, crossbowArrow.EndLine.position, zeroTime); float time = curTime / lineChengeTime; if (time < 1) { return Vector3.Lerp(startPos, vector3, time); } } return vector3; } public float maxSegmentLength = 0.5f; private List CalculateBezierPoint(List curPoints) { List points = new List(); points.Add(curPoints[0]); for (int i = 1; i < curPoints.Count - 1; i++) { points.Add(CalculateBezierPoint(curPoints[i - 1], curPoints[i], curPoints[i + 1], 0.4f)); } points.Add(curPoints[curPoints.Count - 1]); return points; } //2次贝塞尔曲线 private Vector3 CalculateBezierPoint(Vector3 start, Vector3 midPoint, Vector3 end, float t) { Vector3 P0 = start; Vector3 P1 = midPoint; Vector3 P2 = end; float u = 1 - t; float tt = t * t; float uu = u * u; Vector3 p = uu * P0; p += 2 * u * t * P1; p += tt * P2; return p; } private void LateUpdate() { if (crossbow != null && crossbowArrow.gameObject.activeSelf && crossbow.fishingLineRenderer != null && crossbow.fishingLineRenderer.enabled) { // 计算钓鱼线上的点 List linePoints = new List(); linePoints.Add(crossbow.EndLine.position); for (int i = 0; i < crossbow.LineList.Count; i++) { linePoints.Add(crossbow.LineList[i].position); } linePoints.Add(crossbow.TopLine.position); if (state == 1) { List newPoints = new List(); int count = vector3s.Count; for (int i = 0; i < count; i++) { Vector3 vector = GetCurPos(vector3s[i], out float zeroTime); if (zeroTime < 1) { newPoints.Add(vector); } } List refinedPoints = new List(); if (newPoints.Count > 0) { refinedPoints.Add(newPoints[0]); for (int i = 1; i < newPoints.Count; i++) { Vector3 lastPoint = refinedPoints[refinedPoints.Count - 1]; Vector3 currentPoint = newPoints[i]; float distance = Vector3.Distance(lastPoint, currentPoint); if (distance > maxSegmentLength) { int segments = Mathf.FloorToInt(distance / maxSegmentLength); for (int j = 1; j <= segments; j++) { float t = j / (float)segments; Vector3 intermediatePoint = Vector3.Lerp(lastPoint, currentPoint, t); refinedPoints.Add(intermediatePoint); } } else { refinedPoints.Add(currentPoint); } } } refinedPoints.Add(crossbowArrow.EndLine.position); for (int i = 0; i < crossbowArrow.LineList.Count; i++) { refinedPoints.Add(crossbowArrow.LineList[i].position); } linePoints.AddRange(CalculateBezierPoint(refinedPoints)); } else { linePoints.Add(crossbowArrow.LineList[^1].position); } // 绘制钓鱼线 crossbow.fishingLineRenderer.positionCount = linePoints.Count; crossbow.fishingLineRenderer.SetPositions(linePoints.ToArray()); } //} //private void LateUpdate() //{ if (isFinish) { return; } if (Input.GetMouseButtonDown(0)) { _curMousePos = Input.mousePosition; _offsetEuler = Vector3.zero; initialRotation = transform.rotation.eulerAngles; initialRotation.x = CheckAngle(initialRotation.x); initialRotation.y = CheckAngle(initialRotation.y); targetRotation = transform.rotation; } else if (Input.GetMouseButton(0)) { Vector3 ver = Input.mousePosition - _curMousePos; if (ver.magnitude > 5) { _offsetEuler.x -= ver.y * dragCameraScale; _offsetEuler.y += ver.x * dragCameraScale; var targetEulerAngles = initialRotation + _offsetEuler; //Debug.Log($" targetEulerAngles: {targetEulerAngles}"); // Clamp the rotation angles targetEulerAngles.x = Mathf.Clamp(targetEulerAngles.x, -cameraOffset.x, cameraOffset.x); targetEulerAngles.y = Mathf.Clamp(targetEulerAngles.y, -cameraOffset.y, cameraOffset.y); targetEulerAngles.z = 0; _offsetEuler = targetEulerAngles - initialRotation; //Debug.Log($" targetEulerAngles ===: {targetEulerAngles}"); targetRotation = Quaternion.Euler(targetEulerAngles); //transform.rotation = targetRotation; _curMousePos = Input.mousePosition; } transform.rotation = Quaternion.Angle(targetRotation, transform.rotation) > 0.1f ? Quaternion.Lerp(transform.rotation, targetRotation, 0.2f) : targetRotation; } else { if (guide != null) { //Vector3 targetDirection = target.transform.position - crossbowlowCamera.position; //Vector3 currentDirection = crossbowlowCamera.forward; //Quaternion rotationToTarget = Quaternion.FromToRotation(currentDirection, targetDirection); //Quaternion rotation = rotationToTarget * transform.rotation; Quaternion rotation = Quaternion.LookRotation(guide.transform.position - transform.position); rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * 2); transform.eulerAngles = new Vector3(rotation.eulerAngles.x, rotation.eulerAngles.y, 0); } } } }