296 lines
7.8 KiB
C#
296 lines
7.8 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.Rendering;
|
|
|
|
public class GeppettoRunTriggerZone : MonoBehaviour
|
|
{
|
|
[Header("Trigger")]
|
|
public string playerTag = "Player";
|
|
|
|
[Header("Geppetto")]
|
|
public Transform geppetto;
|
|
public Animator geppettoAnimator;
|
|
|
|
[Header("Animation")]
|
|
public string runStateName = "Running";
|
|
public bool playRunAnimationOnTrigger = true;
|
|
|
|
[Header("Move")]
|
|
public float runSpeed = 5f;
|
|
public float rotateSpeed = 12f;
|
|
public bool keepStartY = true;
|
|
|
|
[Header("Player Lock")]
|
|
public bool lockPlayerOnTrigger = true;
|
|
public Transform playerRootToLock; // 비워두면 감지된 VRPlayer root 자동 사용
|
|
public bool lockPlayerRotation = true;
|
|
public Behaviour[] disableWhileEvent; // 이동/회전 관련 컴포넌트 넣고 싶으면 여기에
|
|
|
|
[Header("VR Black Fade")]
|
|
public Camera vrCamera;
|
|
public float fadeDuration = 5f;
|
|
public float quadDistance = 0.45f;
|
|
public float quadScale = 3f;
|
|
|
|
[Header("Scene")]
|
|
public string nextSceneName;
|
|
|
|
private Transform targetPlayer;
|
|
private Transform lockedPlayerRoot;
|
|
private Vector3 lockedPlayerPosition;
|
|
private Quaternion lockedPlayerRotation;
|
|
|
|
private bool started = false;
|
|
private bool sceneChanging = false;
|
|
private float startY;
|
|
|
|
private GameObject blackQuad;
|
|
private Material blackMat;
|
|
|
|
private void Start()
|
|
{
|
|
if (geppetto != null)
|
|
startY = geppetto.position.y;
|
|
|
|
if (geppettoAnimator != null)
|
|
geppettoAnimator.applyRootMotion = false;
|
|
|
|
CreateBlackQuad();
|
|
SetBlackAlpha(0f);
|
|
|
|
if (blackQuad != null)
|
|
blackQuad.SetActive(false);
|
|
}
|
|
|
|
private void OnTriggerEnter(Collider other)
|
|
{
|
|
if (started)
|
|
return;
|
|
|
|
if (!IsPlayer(other))
|
|
return;
|
|
|
|
Debug.Log("제페토 이벤트 구역 진입: " + other.name);
|
|
|
|
lockedPlayerRoot = playerRootToLock != null ? playerRootToLock : other.transform.root;
|
|
targetPlayer = lockedPlayerRoot;
|
|
|
|
if (lockPlayerOnTrigger && lockedPlayerRoot != null)
|
|
{
|
|
lockedPlayerPosition = lockedPlayerRoot.position;
|
|
lockedPlayerRotation = lockedPlayerRoot.rotation;
|
|
|
|
foreach (Behaviour b in disableWhileEvent)
|
|
{
|
|
if (b != null)
|
|
b.enabled = false;
|
|
}
|
|
|
|
Debug.Log("플레이어 위치 고정: " + lockedPlayerRoot.name);
|
|
}
|
|
|
|
started = true;
|
|
|
|
PlayRunAnimation();
|
|
|
|
Collider col = GetComponent<Collider>();
|
|
if (col != null)
|
|
col.enabled = false;
|
|
|
|
StartCoroutine(FadeWhileRunning());
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!started || sceneChanging)
|
|
return;
|
|
|
|
if (geppetto == null || targetPlayer == null)
|
|
return;
|
|
|
|
Vector3 dir = targetPlayer.position - geppetto.position;
|
|
dir.y = 0f;
|
|
|
|
if (dir.sqrMagnitude > 0.001f)
|
|
{
|
|
Quaternion targetRot = Quaternion.LookRotation(dir);
|
|
geppetto.rotation = Quaternion.Slerp(
|
|
geppetto.rotation,
|
|
targetRot,
|
|
Time.deltaTime * rotateSpeed
|
|
);
|
|
|
|
Vector3 nextPos = geppetto.position + dir.normalized * runSpeed * Time.deltaTime;
|
|
|
|
if (keepStartY)
|
|
nextPos.y = startY;
|
|
|
|
geppetto.position = nextPos;
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (!started || sceneChanging)
|
|
return;
|
|
|
|
if (!lockPlayerOnTrigger || lockedPlayerRoot == null)
|
|
return;
|
|
|
|
lockedPlayerRoot.position = lockedPlayerPosition;
|
|
|
|
if (lockPlayerRotation)
|
|
{
|
|
lockedPlayerRoot.rotation = lockedPlayerRotation;
|
|
}
|
|
}
|
|
|
|
private void PlayRunAnimation()
|
|
{
|
|
if (!playRunAnimationOnTrigger)
|
|
return;
|
|
|
|
if (geppettoAnimator == null)
|
|
{
|
|
Debug.LogWarning("Geppetto Animator가 연결되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(runStateName))
|
|
{
|
|
Debug.LogWarning("Run State Name이 비어있습니다.");
|
|
return;
|
|
}
|
|
|
|
geppettoAnimator.applyRootMotion = false;
|
|
geppettoAnimator.Play(runStateName, 0, 0f);
|
|
geppettoAnimator.Update(0f);
|
|
|
|
Debug.Log("달리기 애니메이션 즉시 실행: " + runStateName);
|
|
}
|
|
|
|
private IEnumerator FadeWhileRunning()
|
|
{
|
|
if (blackQuad != null)
|
|
blackQuad.SetActive(true);
|
|
|
|
SetBlackAlpha(0f);
|
|
|
|
float t = 0f;
|
|
|
|
while (t < fadeDuration)
|
|
{
|
|
t += Time.deltaTime;
|
|
float alpha = Mathf.Clamp01(t / fadeDuration);
|
|
SetBlackAlpha(alpha);
|
|
|
|
yield return null;
|
|
}
|
|
|
|
SetBlackAlpha(1f);
|
|
sceneChanging = true;
|
|
|
|
if (!string.IsNullOrWhiteSpace(nextSceneName))
|
|
{
|
|
SceneManager.LoadScene(nextSceneName);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning("Next Scene Name이 비어있습니다.");
|
|
}
|
|
}
|
|
|
|
private void CreateBlackQuad()
|
|
{
|
|
Camera cam = vrCamera != null ? vrCamera : Camera.main;
|
|
|
|
if (cam == null)
|
|
{
|
|
Debug.LogError("VR Camera가 없습니다. Inspector에 Main Camera를 넣어주세요.");
|
|
return;
|
|
}
|
|
|
|
blackQuad = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
|
blackQuad.name = "VR_Black_Fade_Quad";
|
|
|
|
Collider col = blackQuad.GetComponent<Collider>();
|
|
if (col != null)
|
|
Destroy(col);
|
|
|
|
blackQuad.transform.SetParent(cam.transform);
|
|
blackQuad.transform.localPosition = new Vector3(0f, 0f, quadDistance);
|
|
blackQuad.transform.localRotation = Quaternion.identity;
|
|
blackQuad.transform.localScale = new Vector3(quadScale, quadScale, 1f);
|
|
|
|
MeshRenderer renderer = blackQuad.GetComponent<MeshRenderer>();
|
|
blackMat = CreateTransparentBlackMaterial();
|
|
renderer.material = blackMat;
|
|
|
|
renderer.shadowCastingMode = ShadowCastingMode.Off;
|
|
renderer.receiveShadows = false;
|
|
}
|
|
|
|
private Material CreateTransparentBlackMaterial()
|
|
{
|
|
Shader shader =
|
|
Shader.Find("Universal Render Pipeline/Unlit") ??
|
|
Shader.Find("Unlit/Transparent") ??
|
|
Shader.Find("Sprites/Default") ??
|
|
Shader.Find("Standard");
|
|
|
|
Material mat = new Material(shader);
|
|
mat.renderQueue = 5000;
|
|
|
|
if (mat.HasProperty("_BaseColor"))
|
|
mat.SetColor("_BaseColor", new Color(0f, 0f, 0f, 0f));
|
|
|
|
if (mat.HasProperty("_Color"))
|
|
mat.SetColor("_Color", new Color(0f, 0f, 0f, 0f));
|
|
|
|
if (mat.HasProperty("_Surface"))
|
|
mat.SetFloat("_Surface", 1f);
|
|
|
|
if (mat.HasProperty("_Blend"))
|
|
mat.SetFloat("_Blend", 0f);
|
|
|
|
if (mat.HasProperty("_SrcBlend"))
|
|
mat.SetFloat("_SrcBlend", (float)BlendMode.SrcAlpha);
|
|
|
|
if (mat.HasProperty("_DstBlend"))
|
|
mat.SetFloat("_DstBlend", (float)BlendMode.OneMinusSrcAlpha);
|
|
|
|
if (mat.HasProperty("_ZWrite"))
|
|
mat.SetFloat("_ZWrite", 0f);
|
|
|
|
mat.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
|
|
mat.EnableKeyword("_ALPHABLEND_ON");
|
|
|
|
return mat;
|
|
}
|
|
|
|
private void SetBlackAlpha(float alpha)
|
|
{
|
|
if (blackMat == null)
|
|
return;
|
|
|
|
Color c = new Color(0f, 0f, 0f, alpha);
|
|
|
|
if (blackMat.HasProperty("_BaseColor"))
|
|
blackMat.SetColor("_BaseColor", c);
|
|
|
|
if (blackMat.HasProperty("_Color"))
|
|
blackMat.SetColor("_Color", c);
|
|
}
|
|
|
|
private bool IsPlayer(Collider other)
|
|
{
|
|
if (other.CompareTag(playerTag))
|
|
return true;
|
|
|
|
if (other.transform.root.CompareTag(playerTag))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
} |