2025-03-07 16:56:41 +01:00

186 lines
5.7 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BottleSmash : MonoBehaviour {
// Use this for initialization
//all of the required items in order to gie the impression of hte glass breaking.
[ColorUsageAttribute(true, true, 0f, 8f, 0.125f, 3f)]
public Color color;
//to use to find any delta
[SerializeField]
[HideInInspector]
private Color cachedColor;
//used to update any colors when the value changes, not by polling
[SerializeField]
[HideInInspector]
private List<ColorBase> registeredComponents;
public GameObject Cork, Liquid, Glass, Glass_Shattered, Label;
//default despawn time;
public float DespawnTime = 5.0f;
//splash effect.
public ParticleSystem Effect;
//3D mesh on hte ground (given a specific height).
public GameObject Splat;
//such as the ground layer otherwise the broken glass could be considered the 'ground'
public LayerMask SplatMask;
//distance of hte raycast
public float maxSplatDistance = 5.0f;
//if the change in velocity is greater than this THEN it breaks
public float shatterAtSpeed = 2.0f;
//if the is disabled then it wont shatter by itself.
public bool allowShattering = true;
//if it collides with an object then and only then is there a period of 0.2f seconds to shatter.
public bool onlyAllowShatterOnCollision = true;
//for the ability to find the change in velocity.
[SerializeField]
[HideInInspector]
private Vector3 previousPos;
[SerializeField]
[HideInInspector]
private Vector3 previousVelocity;
[SerializeField]
[HideInInspector]
private Vector3 randomRot;
[SerializeField]
[HideInInspector]
private float _lastHitSpeed = 0;
//dont break if we have already broken, only applies to self breaking logic, not by calling Smash()
bool broken = false;
//timeout
float collidedRecently = -1;
void Start () {
previousPos = transform.position;
}
//Smash function so it can be tied to buttons.
public void RandomizeColor()
{
color = new Color(Random.Range(0, 1), Random.Range(0, 1), Random.Range(0, 1), 1);
}
void OnCollisionEnter(Collision collision)
{
//set a timer for about 0.2s to be able to be broken
_lastHitSpeed = collision.impulse.magnitude;
if (collision.transform.tag != "Liquid")
collidedRecently = 0.2f;
}
public void AttemptCollision(Collision col)
{
OnCollisionEnter(col);
}
public void RegisterColorBase(ColorBase cb)
{
registeredComponents.Add(cb);
}
public void ChangedColor()
{
if(cachedColor != color)
{
cachedColor = color;
//update all registered components
foreach (ColorBase cb in registeredComponents)
{
cb.Unify();
}
}
}
public Vector3 GetRandomRotation()
{
return randomRot;
}
public void RandomRotation()
{
randomRot = (Random.insideUnitSphere + Vector3.forward).normalized;
}
public void Smash()
{
broken = true;
//the Corks collider needs to be turned on;
if (Cork != null)
{
Cork.transform.parent = null;
Cork.GetComponent<Collider>().enabled = true;
Cork.GetComponent<Rigidbody>().isKinematic = false;
Destroy(Cork.gameObject, DespawnTime);
}
//the Liquid gets removed after n seconds
if (Liquid != null)
{
float t = 0.0f;
//if (Effect != null)
// t = (Effect.main.startLifetime.constantMin + Effect.main.startLifetime.constantMax)/2;
Destroy(Liquid.gameObject, t);
}
//particle effect
if(Effect != null)
{
Effect.Play();
Destroy(Effect.gameObject, Effect.main.startLifetime.constantMax);
}
//now the label;
if (Label != null)
{
//Label.transform.parent = null;
//Label.GetComponent<Collider>().enabled = true;
//Label.GetComponent<Rigidbody>().isKinematic = false;
Destroy(Label.gameObject);
}
//turn Glass off and the shattered on.
if (Glass != null)
{
Destroy(Glass.gameObject);
}
if (Glass_Shattered != null)
{
Glass_Shattered.SetActive(true);
Glass_Shattered.transform.parent = null;
Destroy(Glass_Shattered, DespawnTime);
}
//instantiate the splat.
RaycastHit info = new RaycastHit();
if(Splat != null)
if (Physics.Raycast(transform.position, Vector3.down, out info, maxSplatDistance, SplatMask))
{
GameObject newSplat = Instantiate(Splat);
newSplat.transform.position = info.point;
}
Destroy(transform.gameObject, DespawnTime);
}
// Update is called once per frame, for the change in velocity and all that jazz...
void FixedUpdate () {
ChangedColor();
collidedRecently -= Time.deltaTime;
Vector3 currentVelocity = (transform.position - previousPos) / Time.fixedDeltaTime;
if ((onlyAllowShatterOnCollision && collidedRecently >= 0.0f) | !onlyAllowShatterOnCollision)
{
if (allowShattering)
{
if (Vector3.Distance(currentVelocity, previousVelocity) > shatterAtSpeed || _lastHitSpeed > shatterAtSpeed)
{
if (!broken)
Smash();
}
}
}
_lastHitSpeed = 0;
previousVelocity = currentVelocity;
previousPos = transform.position;
}
}