using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class Arrow : MonoBehaviour { private Rigidbody newRigidbody; public Vector3 shootOutPosition; public float flyTime = 0; public bool isHit = false; public RaycastHit raycastHit; private float mySpeed = 0; public bool simulatedParabola = false; //模拟抛物线 public ArmBow armBow; public static float speed = GameMgr.RealSizeToGameSize(60); void Awake() { GameMgr.ins.gameMode.PauseTimeCounting(this); } void Start() { newRigidbody = this.gameObject.AddComponent(); mySpeed = speed; if (GameAssistUI.ins) { mySpeed *= (1 + GameAssistUI.ins.shootScaleValue); } //预测和判断是否需要抛物线动画 if (raycastHit.transform.gameObject.name == "TargetBody") { // Vector3 targetPosition = raycastHit.transform.position; // Vector3 tailPosition = this.transform.position; // float moveDistance = Vector3.Distance(targetPosition, tailPosition); // float canFlyTime = Mathf.Sqrt(tailPosition.y * 2 / 9.81f); // float estimateTime = moveDistance / mySpeed; // // if (estimateTime < canFlyTime) { // // float t = 1.5f; // // float g = 9.81f; // // float vy = g * t / 2; // // float vx = moveDistance / t; // // newRigidbody.velocity = new Vector3(0, vy, vx); // // mySpeed = newRigidbody.velocity.magnitude; // // } ApplyParabolaAngle(raycastHit.point); float distance = TargetBody.ins.GetDistance(); if (Mathf.RoundToInt(distance) >= 50) { if (Random.value < 0.5) simulatedParabola = true; } } newRigidbody.velocity = this.transform.forward * mySpeed; newRigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; Transform cameraTF = this.transform.Find("Camera"); cameraTF.gameObject.SetActive(true); cameraTF.gameObject.AddComponent().arrow = this; this.activeEffectTrail(true); } void ApplyParabolaAngle(Vector3 destination) { float angleX = 0; float distX = Vector2.Distance( new Vector2(destination.x, destination.z), new Vector2(this.transform.position.x, this.transform.position.z) ); float distY = destination.y - this.transform.position.y; float posBase = (Physics.gravity.y * Mathf.Pow(distX, 2.0f)) / (2.0f * Mathf.Pow(mySpeed, 2.0f)); float posX = distX / posBase; float posY = (Mathf.Pow(posX, 2.0f) / 4.0f) - ((posBase - distY) / posBase); bool paoshe = false; if (posY >= 0.0f) { if (paoshe) angleX = Mathf.Rad2Deg * Mathf.Atan(-posX / 2.0f + Mathf.Pow(posY, 0.5f)); else angleX = Mathf.Rad2Deg * Mathf.Atan(-posX / 2.0f - Mathf.Pow(posY, 0.5f)); } else { angleX = 45.0f; } Debug.LogWarning(angleX); // bool hasBestAngle = false; // for (float angle = -5.0f; angle < 20.0f; angle += 0.3f) { // float vx = mySpeed * Mathf.Cos(angle / Mathf.Rad2Deg); // float vy = mySpeed * Mathf.Sin(angle / Mathf.Rad2Deg); // // vx * t = distX; // float t = distX / vx; // // vy * t + 1/2 * Physics.gravity.y * Mathf.Pow(t, 2) = distY; // float realY = vy * t + 1/2 * Physics.gravity.y * Mathf.Pow(t, 2); // if (Mathf.Abs(realY - distY) < 0.3f) { // angleX = angle; // hasBestAngle = true; // // Debug.Log("disY" + Mathf.Abs(realY - distY) + " angleX:" + angleX + " realY:" + realY + " distY:" + distY); // Debug.Log() // break; // } // } // if (hasBestAngle) { // // Debug.Log(angleX); // } else { // angleX = 20; // Debug.Log("AAA"); // } Vector3 finalAngle = this.transform.eulerAngles; finalAngle = new Vector3(-angleX, finalAngle.y, finalAngle.z); this.transform.localRotation = Quaternion.Euler(finalAngle); } void OnDestroy() { GameMgr.ins.gameMode.ResumeTimeCounting(this); if (this.newRigidbody) { Destroy(this.newRigidbody); } } Vector3 position; Quaternion rotation; void FixedUpdate() { if (newRigidbody) { transform.forward = newRigidbody.velocity.normalized; } if (!isHit && flyTime >= 0) { flyTime += Time.deltaTime; this.position = this.transform.position; this.rotation = this.transform.rotation; if (flyTime > 14) { Destroy(gameObject); GameMgr.ins.gameMode.HitTarget(0); AudioMgr.ins.PlayCheer(false); nextShoot(); } this.UpdateRotate(); } // this.UpdateShake(); } public void Hit() { gameObject.GetComponent().enabled = false; if (newRigidbody) { newRigidbody.useGravity = false; newRigidbody.velocity = Vector3.zero; Destroy(newRigidbody); newRigidbody = null; } isHit = true; // this.Shake(); this.activeEffectCyclone(false); this.activeEffectBomb(true); this.activeEffectTrail(false); } public Vector3 getHeadPosition() { return this.transform.Find("Head").position; } /**箭矢旋转 */ private Vector3 rotateV3 = new Vector3(0, 0, 1400); private void UpdateRotate() { this.transform.Find("Head").Rotate(rotateV3 * Time.deltaTime, Space.Self); } /**箭矢震动 */ private bool shaking = false; private float shakeTime = 0; private float shakeTimeMax = 0.5f; private float shakeRange = 5; private int shakeDirection = 1; private Vector3 shakeAngles = new Vector3(); private void Shake() { this.shaking = true; this.shakeTime = 0; this.shakeDirection = 1; } private void UpdateShake() { if (!this.shaking) { return; } Transform transform = this.transform.Find("Head").transform; float shakeRangeNow = (1 - this.shakeTime / this.shakeTimeMax) * this.shakeRange; if (shakeRangeNow <= 0) {//震动结束 this.shaking = false; this.shakeAngles.x = 0; } else { this.shakeAngles.x = -this.shakeDirection * shakeRangeNow; this.shakeDirection *= -1; } transform.localEulerAngles = this.shakeAngles; this.shakeTime += Time.deltaTime; } //进入下一轮射击 bool hasDoneNextShoot = false; public void nextShoot() { if (hasDoneNextShoot) return; hasDoneNextShoot = true; GameMgr.ins.gameMode.ResumeTimeCounting(this); if (!GameMgr.ins.gameMode.DoNextShoot()) return; this.armBow.readyShoot(); } void OnCollisionEnter(Collision collision) { if ((1 << collision.gameObject.layer) != LayerMask.GetMask("Target")) { this.Hit(); GameMgr.ins.gameMode.HitTarget(0); AudioMgr.ins.PlayCheer(false); } this.transform.SetParent(collision.transform.parent); } public void activeEffectCyclone(bool value) { this.transform.Find("Head/EF_kuosanquan").gameObject.SetActive(value); if (!value) return; ParticleSystemRenderer ps = this.transform.Find("Head/EF_kuosanquan/kuosan").GetComponent(); ParticleSystemRenderer ps1 = this.transform.Find("Head/EF_kuosanquan/kuosan (1)").GetComponent(); DOTween.To(() => ps.minParticleSize, value => { ps.minParticleSize = value; ps.maxParticleSize = value; }, 0.4f, 0.6f); DOTween.To(() => ps1.minParticleSize, value => { ps1.minParticleSize = value; ps1.maxParticleSize = value; }, 0.8f, 0.6f); } void activeEffectBomb(bool value) { this.transform.Find("Head/EF_baodian").gameObject.SetActive(value); } void activeEffectTrail(bool value) { this.transform.Find("EF_tuowei").gameObject.SetActive(value); this.transform.Find("EF_tuowei/Trail").GetComponent().time = 1.6f / mySpeed; } }