제페토 첫씬 끝

This commit is contained in:
dldydtn9755-crypto
2026-06-25 17:28:18 +09:00
parent 246afce4c4
commit 2aebeb1e9f
5 changed files with 809 additions and 92 deletions

View File

@@ -1,7 +1,7 @@
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Rendering;
public class GeppettoRunTriggerZone : MonoBehaviour
{
@@ -11,39 +11,56 @@ public class GeppettoRunTriggerZone : MonoBehaviour
[Header("Geppetto")]
public Transform geppetto;
public Animator geppettoAnimator;
public string runBoolName = "isRunning";
[Header("Animation")]
public string runStateName = "Running";
public bool playRunAnimationOnTrigger = true;
[Header("Move")]
public float runSpeed = 5f;
public float rotateSpeed = 8f;
public float fadeDistance = 2f;
public float rotateSpeed = 12f;
public bool keepStartY = true;
[Header("Fade")]
public Image blackFadeImage;
public float fadeDuration = 1f;
[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 fading = false;
private bool sceneChanging = false;
private float startY;
private GameObject blackQuad;
private Material blackMat;
private void Start()
{
if (blackFadeImage != null)
{
blackFadeImage.gameObject.SetActive(true);
if (geppetto != null)
startY = geppetto.position.y;
Color c = blackFadeImage.color;
c.a = 0f;
blackFadeImage.color = c;
}
if (geppettoAnimator != null)
geppettoAnimator.applyRootMotion = false;
if (geppettoAnimator != null && !string.IsNullOrEmpty(runBoolName))
{
geppettoAnimator.SetBool(runBoolName, false);
}
CreateBlackQuad();
SetBlackAlpha(0f);
if (blackQuad != null)
blackQuad.SetActive(false);
}
private void OnTriggerEnter(Collider other)
@@ -56,24 +73,37 @@ private void OnTriggerEnter(Collider other)
Debug.Log("Á¦ÆäÅä À̺¥Æ® ±¸¿ª ÁøÀÔ: " + other.name);
targetPlayer = other.transform;
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;
if (geppettoAnimator != null && !string.IsNullOrEmpty(runBoolName))
{
geppettoAnimator.SetBool(runBoolName, true);
}
PlayRunAnimation();
Collider triggerCollider = GetComponent<Collider>();
if (triggerCollider != null)
{
triggerCollider.enabled = false;
}
Collider col = GetComponent<Collider>();
if (col != null)
col.enabled = false;
StartCoroutine(FadeWhileRunning());
}
private void Update()
{
if (!started || fading)
if (!started || sceneChanging)
return;
if (geppetto == null || targetPlayer == null)
@@ -82,34 +112,70 @@ private void Update()
Vector3 dir = targetPlayer.position - geppetto.position;
dir.y = 0f;
float distance = dir.magnitude;
if (dir.sqrMagnitude > 0.001f)
{
Quaternion targetRotation = Quaternion.LookRotation(dir);
Quaternion targetRot = Quaternion.LookRotation(dir);
geppetto.rotation = Quaternion.Slerp(
geppetto.rotation,
targetRotation,
targetRot,
Time.deltaTime * rotateSpeed
);
geppetto.position += dir.normalized * runSpeed * Time.deltaTime;
}
Vector3 nextPos = geppetto.position + dir.normalized * runSpeed * Time.deltaTime;
if (distance <= fadeDistance)
{
StartCoroutine(FadeOutAndLoadScene());
if (keepStartY)
nextPos.y = startY;
geppetto.position = nextPos;
}
}
private IEnumerator FadeOutAndLoadScene()
private void LateUpdate()
{
fading = true;
if (!started || sceneChanging)
return;
if (geppettoAnimator != null && !string.IsNullOrEmpty(runBoolName))
if (!lockPlayerOnTrigger || lockedPlayerRoot == null)
return;
lockedPlayerRoot.position = lockedPlayerPosition;
if (lockPlayerRotation)
{
geppettoAnimator.SetBool(runBoolName, false);
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;
@@ -117,17 +183,14 @@ private IEnumerator FadeOutAndLoadScene()
{
t += Time.deltaTime;
float alpha = Mathf.Clamp01(t / fadeDuration);
if (blackFadeImage != null)
{
Color c = blackFadeImage.color;
c.a = alpha;
blackFadeImage.color = c;
}
SetBlackAlpha(alpha);
yield return null;
}
SetBlackAlpha(1f);
sceneChanging = true;
if (!string.IsNullOrWhiteSpace(nextSceneName))
{
SceneManager.LoadScene(nextSceneName);
@@ -138,6 +201,88 @@ private IEnumerator FadeOutAndLoadScene()
}
}
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))