using MathNet.Numerics; using o0.Wave.RealTime.Old; using ShatterToolkit; using ShatterToolkit.Helpers; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public enum FruitType { Normal, Bomb, FrozenBanana, ComboPomegranate, RainbowApple } public class FruitBehavior : MonoBehaviour { public const float ArrivingDist = 5.0f; [SerializeField] public Material IceMat_NoTex = null; [SerializeField] public Material IceMat_Tex = null; private List> MatBeforeFrost = new List>(); private float Trajectory_coef_a; // y = ax^2 + bx + c private float Trajectory_coef_b; // y = ax^2 + bx + c private float Trajectory_coef_c; // y = ax^2 + bx + c private Vector3 Original_position; private Vector3 Target_position; private float ExistingTime = 0f; private float TrajectoryTime = 0f; private float TrajectoryLifetime = 0f; public bool bMoveAlongTrajectory = true; private Vector3 SpinAxis; private float SpinSpeed; private FruitType Type; private GamingManager _gamingManager; private Material PostSplitMat; private GameObject JuiceSplash; public Sprite JuiceStain; public delegate void ArriveDelegate(FruitBehavior fb); public delegate void OnHitDelegete(FruitBehavior fb, Vector3 hit_p, bool bCritical); public event ArriveDelegate OnArrive; public event OnHitDelegete OnHitEvent; private GameObject MeshParent; public FruitType GetFruitType() { return Type; } // Which meshes should be shattered private List ToShatter = new List(); void Awake() { } private void Start() { } // Update is called once per frame void Update() { if (!_gamingManager.IsGamePaused()) { ExistingTime += Time.deltaTime; if (transform.position.z < ArrivingDist) { OnArrive.Invoke(this); } if (Type == FruitType.ComboPomegranate || Type == FruitType.RainbowApple || Type == FruitType.FrozenBanana) { MeshRenderer[] renderers = GetComponentsInChildren(); foreach (var renderer in renderers) { Material[] mats = renderer.materials; foreach (var mat in mats) { float sin_x = ExistingTime * Mathf.PI * 2f; float sin_y = Mathf.Sin(sin_x); float value = (sin_y + 1f) * 0.5f * 0.65f; Color flicker = new Color(value, value, value); mat.SetColor("_EmissionColor", flicker); } } } } // Moves along trajectory, if not in combo pomegranate time if (bMoveAlongTrajectory) { TrajectoryTime += Time.deltaTime; float parabola_x = Mathf.Lerp(Original_position.z, Target_position.z, TrajectoryTime / TrajectoryLifetime); float parabola_y = Trajectory_coef_a * parabola_x * parabola_x + Trajectory_coef_b * parabola_x + Trajectory_coef_c; float pos_x = Mathf.Lerp(Original_position.x, Target_position.x, TrajectoryTime / TrajectoryLifetime); gameObject.transform.position = new Vector3(pos_x, parabola_y, parabola_x); // Random spinning transform.Rotate(SpinAxis, Time.deltaTime * SpinSpeed); } } //枪设备下设置碰撞层和tag string tagToSet = "Fruit"; string layerToSet = "Target1"; public void Init(FruitType ty, GamingManager manager, Vector3 spawnLocation, Vector3 targetLocation, float timeToArraive) { _gamingManager = manager; Type = ty; Original_position = spawnLocation; Target_position = targetLocation; GamingValues.CalcTrajectoryEquationCoef(spawnLocation, targetLocation, out Trajectory_coef_a, out Trajectory_coef_b, out Trajectory_coef_c); TrajectoryLifetime = timeToArraive; GameObject fruit = _gamingManager.gameObject.GetComponent().GetFruit(ty, true, out PostSplitMat, out JuiceSplash, out JuiceStain); MeshParent = Instantiate(fruit, gameObject.transform); //SphereCollider sphr_collider = meshParent.GetComponent(); //if (sphr_collider) //{ // SphereCollider _collider = gameObject.AddComponent(); // _collider.isTrigger = true; // _collider.radius = sphr_collider.radius; //} if (GlobalData.MyDeviceMode == DeviceMode.Gun) { gameObject.tag = tagToSet; gameObject.layer = LayerMask.NameToLayer(layerToSet); MeshParent.tag = tagToSet; MeshParent.layer = LayerMask.NameToLayer(layerToSet); } Rigidbody _body = gameObject.AddComponent(); _body.isKinematic = true; _body.useGravity = false; //Destroy(GetComponent()); // Find out which meshes will participate in shattering for (int i = 0; i < MeshParent.transform.childCount; i++) { GameObject go = MeshParent.transform.GetChild(i).gameObject; if (go.CompareTag("ShatterIncluded")) { if (GlobalData.MyDeviceMode == DeviceMode.Gun) { go.tag = tagToSet; go.layer = LayerMask.NameToLayer(layerToSet); } ShatterTool st = go.AddComponent(); PieceRemover pr = go.AddComponent(); st.GenerationLimit = 2; pr.startAtGeneration = 2; pr.timeDelay = 1f; st.SendPostSplitMessage = true; go.AddComponent(); ToShatter.Add(go); } // Backup the origin mats of the fruit, used to recover from forst MeshRenderer renderer = go.GetComponent(); MatBeforeFrost.Add(new List()); foreach (var mat in renderer.materials) { MatBeforeFrost[i].Add(mat); } } // If this is a ComboPomegarante, add a specialized behavior component if (Type == FruitType.ComboPomegranate) { gameObject.AddComponent().Init(_gamingManager); } // Get a random rotation axis and speed SpinAxis = Random.rotation * Vector3.forward; SpinSpeed = Random.Range(90f, 180f); } private void OnTriggerEnter(Collider other) { //水果爆炸不拦截 // If is hit by a fullscreen clearing bubble FullscreenClearBubbleBehavior bubble = other.gameObject.GetComponent(); if (bubble) { OnHitEvent.Invoke(this, gameObject.transform.position, false); return; } //拦截子弹碰撞 if (GlobalData.MyDeviceMode == DeviceMode.Gun) return; // If is hit by an arrow ArrowBehavior arrow = other.gameObject.GetComponent(); if (arrow) { arrow.HitAFruit(); float fruit_dist = gameObject.transform.position.magnitude; Vector3 point_along_arrow_dir = (arrow.transform.position.normalized * fruit_dist); if ((point_along_arrow_dir - gameObject.transform.position).magnitude <= 1f) { OnHitEvent.Invoke(this, other.ClosestPoint(gameObject.transform.position), true); } else { OnHitEvent.Invoke(this, other.ClosestPoint(gameObject.transform.position), false); } return; } } public void OnHitCollision(Collider other, ArrowBehavior shootObj) { // If is hit by an arrow if (shootObj) { shootObj.HitAFruit(); float fruit_dist = gameObject.transform.position.magnitude; Vector3 point_along_arrow_dir = (shootObj.transform.position.normalized * fruit_dist); if ((point_along_arrow_dir - gameObject.transform.position).magnitude <= 1f) { OnHitEvent.Invoke(this, other.ClosestPoint(gameObject.transform.position), true); } else { OnHitEvent.Invoke(this, other.ClosestPoint(gameObject.transform.position), false); } return; } // If is hit by a fullscreen clearing bubble FullscreenClearBubbleBehavior bubble = other.gameObject.GetComponent(); if (bubble) { OnHitEvent.Invoke(this, gameObject.transform.position, false); return; } } // Play smashing effect, including shattering the mesh and instantiate an smashing audio which will be delay-destroyed public void SmashEffect() { foreach (var go in ToShatter) { Rigidbody rb = go.AddComponent(); rb.mass = 1.0f; // add rigidbody right before shatter this mesh, then it will be destroyed along with the gameobject rb.angularDrag = 5f; PostSplitBehaviour psb = go.AddComponent(); psb.PostSplitMat = PostSplitMat; psb.ExplosionPosition = gameObject.transform.position; go.SendMessage("Shatter", gameObject.transform.position); } GameObject fruitJuice = Instantiate(JuiceSplash, gameObject.transform.position, Quaternion.identity); AudioSource audio = fruitJuice.AddComponent(); audio.clip = _gamingManager.GetAudioManager().GetRandomSound((Type == FruitType.Bomb) ? SoundCategory.BombExplode : SoundCategory.FruitSmash); if (UserSettings.ins.openEffect) audio.Play(); GamingManager.DelayDestroy(_gamingManager, fruitJuice, (Type == FruitType.Bomb) ? 3f : 1.5f); Destroy(gameObject); } public void Frost() { Debug.Log("Start Frost"); for (int i = 0; i < MeshParent.transform.childCount; i++) { GameObject go = MeshParent.transform.GetChild(i).gameObject; MeshRenderer renderer = go.GetComponent(); Material[] iced_mats = new Material[renderer.materials.Length]; for (int j = 0; j < renderer.materials.Length; j++) { Color originColor = renderer.materials[j].color; if (renderer.materials[j].mainTexture == null) { iced_mats[j] = new Material(IceMat_Tex); } else { iced_mats[j] = new Material(IceMat_NoTex); iced_mats[j].SetColor("_MainCol", originColor); } } renderer.materials = iced_mats; } } public void UnFrost() { for (int i = 0; i < MeshParent.transform.childCount; i++) { GameObject go = MeshParent.transform.GetChild(i).gameObject; MeshRenderer renderer = go.GetComponent(); Material[] new_mats = new Material[renderer.materials.Length]; for (int j = 0; j < renderer.materials.Length; j++) { new_mats[j] = MatBeforeFrost[i][j]; } renderer.materials = new_mats; } } }