Add NegrBagrJaromirJagr minigame
This commit is contained in:
194
Assets/GlassRingController.cs
Normal file
194
Assets/GlassRingController.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class GlassRingController : MonoBehaviour
|
||||
{
|
||||
[Header("Auto Setup")]
|
||||
public bool autoCollectOnAwake = true;
|
||||
public bool includeInactive = true;
|
||||
public float pieceMaxHealth = 100f;
|
||||
|
||||
[Header("Rotation")]
|
||||
public float rotationSpeedDegrees = 45f;
|
||||
|
||||
[Header("Audio")]
|
||||
public AudioSource audioSource;
|
||||
public AudioClip damageClip;
|
||||
public AudioClip breakClip;
|
||||
[Range(0f, 1f)] public float damageVolume = 0.7f;
|
||||
[Range(0f, 1f)] public float breakVolume = 1f;
|
||||
|
||||
private GlassPiece[] pieces;
|
||||
public GlassPiece[] Pieces => pieces;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (audioSource == null)
|
||||
audioSource = GetComponent<AudioSource>();
|
||||
|
||||
if (audioSource == null)
|
||||
audioSource = gameObject.AddComponent<AudioSource>();
|
||||
|
||||
if (Application.isPlaying && autoCollectOnAwake)
|
||||
{
|
||||
CollectPiecesFromChildren();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!Application.isPlaying || Mathf.Abs(rotationSpeedDegrees) < 0.001f)
|
||||
return;
|
||||
|
||||
transform.Rotate(Vector3.right, rotationSpeedDegrees * Time.deltaTime, Space.World);
|
||||
}
|
||||
|
||||
[ContextMenu("Collect Pieces From Children")]
|
||||
public void CollectPiecesFromChildren()
|
||||
{
|
||||
List<GlassPiece> foundPieces = new List<GlassPiece>();
|
||||
|
||||
Transform[] allChildren = GetComponentsInChildren<Transform>(includeInactive);
|
||||
|
||||
foreach (Transform t in allChildren)
|
||||
{
|
||||
if (t == transform) continue;
|
||||
|
||||
Renderer rend = t.GetComponent<Renderer>();
|
||||
if (rend == null)
|
||||
rend = t.GetComponentInChildren<Renderer>();
|
||||
|
||||
if (rend == null)
|
||||
continue;
|
||||
|
||||
Collider col = t.GetComponent<Collider>();
|
||||
|
||||
bool invalidMeshCollider = false;
|
||||
MeshCollider existingMeshCollider = col as MeshCollider;
|
||||
if (existingMeshCollider != null && existingMeshCollider.sharedMesh == null)
|
||||
{
|
||||
invalidMeshCollider = true;
|
||||
}
|
||||
|
||||
if (col == null || invalidMeshCollider)
|
||||
{
|
||||
if (invalidMeshCollider)
|
||||
Destroy(existingMeshCollider);
|
||||
|
||||
BoxCollider box = t.GetComponent<BoxCollider>();
|
||||
if (box == null)
|
||||
box = t.gameObject.AddComponent<BoxCollider>();
|
||||
|
||||
Bounds worldBounds = rend.bounds;
|
||||
Vector3 localCenter = t.InverseTransformPoint(worldBounds.center);
|
||||
|
||||
box.center = localCenter;
|
||||
|
||||
Vector3 lossy = t.lossyScale;
|
||||
box.size = new Vector3(
|
||||
worldBounds.size.x / Mathf.Max(lossy.x, 0.0001f),
|
||||
worldBounds.size.y / Mathf.Max(lossy.y, 0.0001f),
|
||||
worldBounds.size.z / Mathf.Max(lossy.z, 0.0001f)
|
||||
);
|
||||
|
||||
col = box;
|
||||
}
|
||||
|
||||
GlassPiece piece = t.GetComponent<GlassPiece>();
|
||||
if (piece == null)
|
||||
piece = t.gameObject.AddComponent<GlassPiece>();
|
||||
|
||||
Rigidbody rb = t.GetComponent<Rigidbody>();
|
||||
if (rb == null)
|
||||
rb = t.gameObject.AddComponent<Rigidbody>();
|
||||
|
||||
rb.isKinematic = true;
|
||||
rb.useGravity = false;
|
||||
|
||||
foundPieces.Add(piece);
|
||||
}
|
||||
|
||||
foundPieces.Sort((a, b) =>
|
||||
{
|
||||
float angleA = Mathf.Atan2(a.transform.localPosition.z, a.transform.localPosition.x);
|
||||
float angleB = Mathf.Atan2(b.transform.localPosition.z, b.transform.localPosition.x);
|
||||
return angleA.CompareTo(angleB);
|
||||
});
|
||||
|
||||
pieces = foundPieces.ToArray();
|
||||
|
||||
for (int i = 0; i < pieces.Length; i++)
|
||||
{
|
||||
pieces[i].Initialize(i, pieceMaxHealth);
|
||||
}
|
||||
|
||||
Debug.Log($"GlassRingController: collected {pieces.Length} pieces.");
|
||||
}
|
||||
|
||||
public void ApplyProjectileImpact(int hitIndex, ProjectileBehaviour projectile, float charge01, Vector3 hitPoint)
|
||||
{
|
||||
if (pieces == null || pieces.Length == 0) return;
|
||||
|
||||
float sigma = Mathf.Max(0.01f, projectile.sigma);
|
||||
float chargeMultiplier = 0.55f + 1.45f * Mathf.Pow(charge01, 1.4f);
|
||||
|
||||
bool anyHealthChanged = false;
|
||||
bool anyNewBreak = false;
|
||||
|
||||
for (int i = 0; i < pieces.Length; i++)
|
||||
{
|
||||
GlassPiece piece = pieces[i];
|
||||
if (piece == null || piece.IsBroken) continue;
|
||||
|
||||
int d = CircularDistance(i, hitIndex, pieces.Length);
|
||||
float gaussian = Mathf.Exp(-(d * d) / (2f * sigma * sigma));
|
||||
|
||||
if (gaussian < 0.005f) continue;
|
||||
|
||||
float damage = projectile.baseDamage * chargeMultiplier * gaussian;
|
||||
if (i == hitIndex)
|
||||
damage *= projectile.directHitMultiplier;
|
||||
|
||||
Vector3 impulseDir = piece.transform.position - hitPoint;
|
||||
if (impulseDir.sqrMagnitude < 0.0001f)
|
||||
impulseDir = piece.transform.position - transform.position;
|
||||
|
||||
float impulse = projectile.breakImpulse * chargeMultiplier * gaussian;
|
||||
if (i == hitIndex)
|
||||
impulse *= projectile.directHitMultiplier;
|
||||
|
||||
bool brokeNow = piece.ApplyDamage(damage, hitPoint, impulseDir, impulse);
|
||||
|
||||
anyHealthChanged = true;
|
||||
if (brokeNow)
|
||||
anyNewBreak = true;
|
||||
}
|
||||
|
||||
if (anyNewBreak)
|
||||
{
|
||||
PlayBreakSound();
|
||||
}
|
||||
else if (anyHealthChanged)
|
||||
{
|
||||
PlayDamageSound();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlayDamageSound()
|
||||
{
|
||||
if (audioSource != null && damageClip != null)
|
||||
audioSource.PlayOneShot(damageClip, damageVolume);
|
||||
}
|
||||
|
||||
private void PlayBreakSound()
|
||||
{
|
||||
if (audioSource != null && breakClip != null)
|
||||
audioSource.PlayOneShot(breakClip, breakVolume);
|
||||
}
|
||||
|
||||
private int CircularDistance(int a, int b, int count)
|
||||
{
|
||||
int raw = Mathf.Abs(a - b);
|
||||
return Mathf.Min(raw, count - raw);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user