Files
VFSUnity/Assets/Scripts/Interaction/PingClickHandler.cs
T
2026-07-09 02:35:28 +08:00

148 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
public class PingClickHandler : MonoBehaviour
{
public GameObject chanraoObject, nextPing;
public int pingIndex;
private MeshRenderer _modelRenderer, _outlineMesh;
private bool _modelShown;
private bool _isBlinking;
public bool CanBeClicked() { return _isBlinking; }
void OnEnable()
{
_modelRenderer = GetComponent<MeshRenderer>();
if (_modelRenderer == null) _modelRenderer = GetComponentInChildren<MeshRenderer>();
foreach (var r in GetComponentsInChildren<Renderer>(true)) r.enabled = false;
if (GetComponent<Collider>() == null) gameObject.AddComponent<SphereCollider>().radius = 0.5f;
CreateOutlineMesh();
_modelShown = false;
_isBlinking = true;
StopAllCoroutines();
StartCoroutine(BlinkOutline());
}
void CreateOutlineMesh()
{
if (_outlineMesh != null) return;
var mf = GetComponent<MeshFilter>();
if (mf == null) mf = GetComponentInChildren<MeshFilter>();
if (mf == null || mf.sharedMesh == null) return;
var shader = Shader.Find("Custom/OutlineUnlit");
if (shader == null) return;
var mat = new Material(shader);
mat.SetColor("_OutlineColor", new Color(0.2f, 0.5f, 1f, 1f));
mat.SetColor("_MainColor", new Color(0, 0, 0, 0));
mat.SetFloat("_OutlineWidth", OutlineConfig.Width);
var go = new GameObject("Outline");
go.transform.SetParent(transform, false);
// 稍微往上偏移一点点,防止边框插进地里
go.transform.position += Vector3.up * 0.05f;
go.AddComponent<MeshFilter>().sharedMesh = mf.sharedMesh;
_outlineMesh = go.AddComponent<MeshRenderer>();
_outlineMesh.material = mat;
}
System.Collections.IEnumerator BlinkOutline()
{
if (_outlineMesh != null) _outlineMesh.enabled = true;
yield return new WaitForSeconds(0.4f);
while (true) { if (_outlineMesh != null) _outlineMesh.enabled = !_outlineMesh.enabled; yield return new WaitForSeconds(0.4f); }
}
void OnMouseDown()
{
PerformClick();
}
public void PerformClick()
{
foreach (var c in Object.FindObjectsOfType<Camera>())
{
if (!c.enabled) continue;
foreach (var h in Physics.RaycastAll(c.ScreenPointToRay(Input.mousePosition)))
if (h.collider?.transform.parent?.name == "touchArray") return;
}
if (!_modelShown)
{
_modelShown = true;
_isBlinking = false;
StopAllCoroutines();
if (_modelRenderer != null) _modelRenderer.enabled = true;
foreach (var r in GetComponentsInChildren<Renderer>(true)) r.enabled = true;
if (_outlineMesh != null) _outlineMesh.enabled = false;
if (nextPing != null) nextPing.SetActive(true);
else
{
// 如果 nextPing 是 null,说明我是最后一个 ping(也就是 ping.001
// 此时所有的 ping 都已经显示了模型,进入阶段二:重新点亮所有的 ping 边框
var allPings = Object.FindObjectsOfType<PingClickHandler>();
foreach (var p in allPings)
{
p.ReEnableBorder();
}
Debug.Log($"[PingClick] {name} 是最后一个 ping,所有边框已重新激活!");
}
Debug.Log($"[PingClick] {name} 模型显示, 激活 {nextPing?.name}");
var sm = FindObjectOfType<StepManager>();
if (sm != null) sm.RecordPingStep(pingIndex, false);
}
else
{
if (chanraoObject != null) { chanraoObject.SetActive(true); Debug.Log($"[PingClick] {name} → {chanraoObject.name}"); }
gameObject.SetActive(false);
var sm = FindObjectOfType<StepManager>();
if (sm != null) sm.RecordPingStep(pingIndex, true);
// 判断是否是真正的最后一步:检查所有的 PingClickHandler,看是否还有 activeInHierarchy 的。
// 注意当前 gameObject 刚刚被 SetActive(false),所以 FindObjectsOfType 获取不到当前的对象了。
var remainingPings = Object.FindObjectsOfType<PingClickHandler>();
int activePingCount = 0;
foreach (var p in remainingPings)
{
if (p.gameObject.activeInHierarchy) activePingCount++;
}
if (activePingCount == 0)
{
Debug.Log("[PingClick] 所有的 ping 都已经绑成 chanrao 了!播放完成语音。");
var am = FindObjectOfType<AudioManager>();
if (am != null)
{
#if UNITY_EDITOR
var finishClip = UnityEditor.AssetDatabase.LoadAssetAtPath<AudioClip>("Assets/Audio/people/伤员一切正常,包扎完毕.mp3");
if (finishClip != null) am.PlayVoice(finishClip);
#endif
}
}
}
}
public void ReEnableBorder() { _isBlinking = true; if (_outlineMesh != null) { _outlineMesh.enabled = true; StopAllCoroutines(); StartCoroutine(BlinkOutline()); } }
public void UndoSecondClick()
{
gameObject.SetActive(true);
_modelShown = true;
_isBlinking = false;
if (_modelRenderer != null) _modelRenderer.enabled = true;
foreach (var r in GetComponentsInChildren<Renderer>(true)) r.enabled = true;
if (_outlineMesh != null) _outlineMesh.enabled = false;
StopAllCoroutines();
}
public void UndoShow() { gameObject.SetActive(false); }
public void ResetState()
{
_modelShown = false;
_isBlinking = true;
if (_modelRenderer != null) _modelRenderer.enabled = false;
// 隐藏自身模型
foreach (var r in GetComponentsInChildren<Renderer>(true)) { if (_outlineMesh != null && r == _outlineMesh) continue; r.enabled = false; }
if (_outlineMesh != null) _outlineMesh.enabled = true;
StopAllCoroutines();
StartCoroutine(BlinkOutline());
}
}