Merge branch 'feature/hyeonsu-blackjack-clean'

# Conflicts:
#	Assets/01_Scenes/blackjack.unity
#	Assets/01_Scenes/blackjack/NavMesh-Terrain 2.asset
#	Assets/01_Scenes/blackjack/NavMesh-Terrain 2.asset.meta
#	Assets/02_Scripts/Blackjack/HookWalkToTable.cs
#	Assets/04_Models/Blackjack/anim/HookAnimatorController.controller
This commit is contained in:
dldydtn9755-crypto
2026-06-23 18:07:28 +09:00
5 changed files with 82 additions and 431 deletions

Binary file not shown.

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 05b37f77d4689fc41a87b1f3a8b6062a
guid: d25fd4971f21acc41b07b09b612c6ee9
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000

View File

@@ -1,7 +1,7 @@
using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
using UnityEngine.InputSystem;
public class HookWalkToTable : MonoBehaviour
{
@@ -9,9 +9,8 @@ public class HookWalkToTable : MonoBehaviour
public Transform tableFrontPoint;
public Transform chairFrontPoint;
[Header("Pose Points")]
[Header("Sit Point")]
public Transform sitPoint;
public Transform standPoint;
[Header("Move Setting")]
public float arriveBuffer = 0.15f;
@@ -20,57 +19,29 @@ public class HookWalkToTable : MonoBehaviour
public Animator animator;
public string walkBoolName = "isWalking";
public string sitTriggerName = "sitTrigger";
public string standTriggerName = "standTrig";
public string standTriggerName = "standTrigger";
[Header("Sit Correction")]
public bool correctToSitPointAfterSitAnim = true;
public string sitAnimationStateName = "Stand To Sit 0";
public float sitAnimFallbackDuration = 2f;
public float sitCorrectionDuration = 0.45f;
[Header("Auto Stand")]
public bool autoStandAfterSit = false;
public float sitStayDuration = 5f;
[Header("Stand Correction")]
public bool moveToStandPointBeforeStandAnim = true;
public string standAnimationStateName = "Sit To Stand 0";
public float standAnimFallbackDuration = 2f;
public float standCorrectionDuration = 0.45f;
[Header("Wave After Stand")]
public bool waveAfterStand = true;
public Transform lookTarget;
public string waveStateName = "Waving";
public float lookAtTargetDuration = 0.4f;
public float waveCrossFadeDuration = 0.15f;
[Header("Keep Looking While Waving")]
public bool keepLookingAtTargetWhileWaving = true;
public float lookFollowSpeed = 5f;
public float lookYawOffset = 0f;
[Header("Stand Up Setting")]
public float standUpDuration = 1.5f;
[Header("Collision")]
public bool disableCollidersWhenSitting = true;
public bool enableCollidersBeforeStand = true;
public bool enableCollidersAfterStandUp = true;
public Collider[] hookColliders;
[Header("Events")]
public UnityEvent onHookSeated;
[Header("Test")]
public Key testStartKey = Key.T;
public Key testStandUpKey = Key.Y;
private NavMeshAgent agent;
private int step = 0;
private bool isMoving = false;
private bool hasArrived = false;
private bool isSitting = false;
private bool isStanding = false;
private bool isWaving = false;
private bool hasStarted = false;
private bool hookSeatedEventCalled = false;
private bool isStandingUp = false;
private Vector3 currentDestination;
private Coroutine sitRoutine;
private Coroutine standRoutine;
void Start()
{
@@ -99,6 +70,18 @@ void Start()
void Update()
{
// 테스트용: T 누르면 테이블로 이동 후 앉기
if (Keyboard.current != null && Keyboard.current[testStartKey].wasPressedThisFrame)
{
StartWalking();
}
// 테스트용: Y 누르면 일어나기
if (Keyboard.current != null && Keyboard.current[testStandUpKey].wasPressedThisFrame)
{
StandUp();
}
if (!isMoving || agent == null)
{
return;
@@ -117,26 +100,6 @@ void Update()
}
}
void LateUpdate()
{
if (!isWaving)
{
return;
}
if (!keepLookingAtTargetWhileWaving)
{
return;
}
if (lookTarget == null)
{
return;
}
LookAtTargetContinuously();
}
public void StartWalking()
{
if (agent == null)
@@ -151,52 +114,27 @@ public void StartWalking()
return;
}
if (hasStarted || isMoving || isSitting || isStanding || isWaving)
if (isMoving || isSitting || isStandingUp)
{
return;
}
hasStarted = true;
step = 0;
hasArrived = false;
isMoving = true;
isSitting = false;
isStanding = false;
isWaving = false;
hookSeatedEventCalled = false;
EnableHookColliders();
if (sitRoutine != null)
{
StopCoroutine(sitRoutine);
sitRoutine = null;
}
if (standRoutine != null)
{
StopCoroutine(standRoutine);
standRoutine = null;
}
if (animator != null)
{
animator.SetBool(walkBoolName, false);
animator.ResetTrigger(sitTriggerName);
animator.ResetTrigger(standTriggerName);
}
if (!agent.enabled)
{
agent.enabled = true;
}
agent.isStopped = false;
if (animator != null)
{
animator.SetBool(walkBoolName, true);
}
agent.enabled = true;
agent.isStopped = false;
MoveTo(tableFrontPoint);
Debug.Log("Hook starts walking to table front point.");
@@ -206,7 +144,7 @@ void MoveTo(Transform target)
{
NavMeshHit hit;
if (NavMesh.SamplePosition(target.position, out hit, 2f, NavMesh.AllAreas))
if (NavMesh.SamplePosition(target.position, out hit, 1.5f, NavMesh.AllAreas))
{
currentDestination = hit.position;
agent.SetDestination(currentDestination);
@@ -231,15 +169,18 @@ void GoNextStep()
}
else
{
StartSitAnimation();
ArriveAndSit();
}
}
void StartSitAnimation()
void ArriveAndSit()
{
isMoving = false;
hasArrived = true;
isSitting = true;
isStandingUp = false;
// 1. 이동 중지
if (agent != null)
{
agent.isStopped = true;
@@ -247,11 +188,24 @@ void StartSitAnimation()
agent.enabled = false;
}
if (chairFrontPoint != null)
// 2. 앉아 있는 동안 후크 콜라이더 끄기
if (disableCollidersWhenSitting)
{
DisableHookColliders();
}
// 3. 실제 앉을 위치로 강제 이동
if (sitPoint != null)
{
transform.position = sitPoint.position;
transform.rotation = sitPoint.rotation;
}
else if (chairFrontPoint != null)
{
transform.rotation = chairFrontPoint.rotation;
}
// 4. 앉는 애니메이션 실행
if (animator != null)
{
animator.SetBool(walkBoolName, false);
@@ -260,81 +214,24 @@ void StartSitAnimation()
animator.SetTrigger(sitTriggerName);
}
Debug.Log("Hook started sit animation.");
sitRoutine = StartCoroutine(SitRoutine());
}
IEnumerator SitRoutine()
{
yield return StartCoroutine(WaitAnimatorStateEnd(sitAnimationStateName, sitAnimFallbackDuration));
if (correctToSitPointAfterSitAnim && sitPoint != null)
{
yield return StartCoroutine(SmoothMoveTo(sitPoint, sitCorrectionDuration));
Debug.Log("Hook corrected to sit point.");
}
if (disableCollidersWhenSitting)
{
DisableHookColliders();
}
Debug.Log("Hook is now sitting.");
if (!hookSeatedEventCalled)
{
hookSeatedEventCalled = true;
onHookSeated?.Invoke();
}
if (autoStandAfterSit)
{
yield return new WaitForSeconds(sitStayDuration);
StandUp();
}
sitRoutine = null;
Debug.Log("Hook moved to sit point and started sitting.");
}
public void StandUp()
{
if (!isSitting || isStanding)
if (!isSitting || isStandingUp)
{
return;
}
if (sitRoutine != null)
{
StopCoroutine(sitRoutine);
sitRoutine = null;
}
if (standRoutine != null)
{
StopCoroutine(standRoutine);
standRoutine = null;
}
standRoutine = StartCoroutine(StandRoutine());
StartCoroutine(StandUpRoutine());
}
IEnumerator StandRoutine()
IEnumerator StandUpRoutine()
{
isStanding = true;
isStandingUp = true;
isSitting = false;
if (enableCollidersBeforeStand)
{
EnableHookColliders();
}
if (moveToStandPointBeforeStandAnim && standPoint != null)
{
yield return StartCoroutine(SmoothMoveTo(standPoint, standCorrectionDuration));
Debug.Log("Hook moved to stand point before stand animation.");
}
if (animator != null)
{
animator.SetBool(walkBoolName, false);
@@ -343,207 +240,26 @@ IEnumerator StandRoutine()
animator.SetTrigger(standTriggerName);
}
Debug.Log("Hook started stand animation.");
Debug.Log("Hook started stand up animation.");
yield return StartCoroutine(WaitAnimatorStateEnd(standAnimationStateName, standAnimFallbackDuration));
yield return new WaitForSeconds(standUpDuration);
isStanding = false;
Debug.Log("Hook finished standing.");
if (waveAfterStand)
if (enableCollidersAfterStandUp)
{
yield return StartCoroutine(StartWaveLoop());
EnableHookColliders();
}
hasStarted = false;
standRoutine = null;
}
IEnumerator StartWaveLoop()
{
isWaving = true;
if (lookTarget != null)
{
yield return StartCoroutine(SmoothLookAtTarget(lookTarget, lookAtTargetDuration));
Debug.Log("Hook looked at player.");
}
if (animator != null)
{
animator.SetBool(walkBoolName, false);
animator.ResetTrigger(sitTriggerName);
animator.ResetTrigger(standTriggerName);
animator.CrossFade(waveStateName, waveCrossFadeDuration, 0);
Debug.Log("Hook forced Waving state: " + waveStateName);
}
}
void LookAtTargetContinuously()
{
Vector3 direction = lookTarget.position - transform.position;
direction.y = 0f;
if (direction.sqrMagnitude < 0.001f)
{
return;
}
Quaternion targetRotation = Quaternion.LookRotation(direction);
targetRotation *= Quaternion.Euler(0f, lookYawOffset, 0f);
transform.rotation = Quaternion.Slerp(
transform.rotation,
targetRotation,
Time.deltaTime * lookFollowSpeed
);
}
IEnumerator SmoothLookAtTarget(Transform target, float duration)
{
if (target == null)
{
yield break;
}
Vector3 direction = target.position - transform.position;
direction.y = 0f;
if (direction.sqrMagnitude < 0.001f)
{
yield break;
}
Quaternion startRotation = transform.rotation;
Quaternion targetRotation = Quaternion.LookRotation(direction);
targetRotation *= Quaternion.Euler(0f, lookYawOffset, 0f);
if (duration <= 0f)
{
transform.rotation = targetRotation;
yield break;
}
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
t = Mathf.Clamp01(t);
t = Mathf.SmoothStep(0f, 1f, t);
transform.rotation = Quaternion.Slerp(startRotation, targetRotation, t);
yield return null;
}
transform.rotation = targetRotation;
}
IEnumerator WaitAnimatorStateEnd(string stateName, float fallbackDuration)
{
if (animator == null)
{
yield return new WaitForSeconds(fallbackDuration);
yield break;
}
yield return null;
float timer = 0f;
float timeout = 2f;
while (!animator.GetCurrentAnimatorStateInfo(0).IsName(stateName))
{
timer += Time.deltaTime;
if (timer >= timeout)
{
Debug.LogWarning(stateName + " state not found. Fallback wait used.");
yield return new WaitForSeconds(fallbackDuration);
yield break;
}
yield return null;
}
while (true)
{
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (!stateInfo.IsName(stateName))
{
break;
}
if (stateInfo.normalizedTime >= 0.98f)
{
break;
}
yield return null;
}
}
IEnumerator SmoothMoveTo(Transform target, float duration)
{
if (target == null)
{
yield break;
}
if (duration <= 0f)
{
transform.position = target.position;
transform.rotation = target.rotation;
yield break;
}
Vector3 startPosition = transform.position;
Quaternion startRotation = transform.rotation;
Vector3 targetPosition = target.position;
Quaternion targetRotation = target.rotation;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
t = Mathf.Clamp01(t);
t = Mathf.SmoothStep(0f, 1f, t);
transform.position = Vector3.Lerp(startPosition, targetPosition, t);
transform.rotation = Quaternion.Slerp(startRotation, targetRotation, t);
yield return null;
}
transform.position = targetPosition;
transform.rotation = targetRotation;
}
void StopWalking()
{
isMoving = false;
if (agent != null && agent.enabled)
if (agent != null)
{
agent.enabled = true;
agent.isStopped = true;
agent.ResetPath();
}
if (animator != null)
{
animator.SetBool(walkBoolName, false);
}
hasArrived = false;
isStandingUp = false;
Debug.Log("Hook stood up.");
}
void DisableHookColliders()
@@ -578,23 +294,19 @@ void EnableHookColliders()
}
}
public bool IsSitting()
void StopWalking()
{
return isSitting;
}
isMoving = false;
public bool IsStanding()
{
return isStanding;
}
if (agent != null && agent.enabled)
{
agent.isStopped = true;
agent.ResetPath();
}
public bool IsWaving()
{
return isWaving;
}
public bool HasStarted()
{
return hasStarted;
if (animator != null)
{
animator.SetBool(walkBoolName, false);
}
}
}

View File

@@ -148,9 +148,6 @@ AnimatorStateMachine:
- serializedVersion: 1
m_State: {fileID: 9049851607463686061}
m_Position: {x: 840, y: 40, z: 0}
- serializedVersion: 1
m_State: {fileID: 7205364625675609378}
m_Position: {x: -3.49469, y: -15.105026, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions:
- {fileID: -5852507744452669881}
@@ -182,15 +179,9 @@ AnimatorController:
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 1
m_DefaultBool: 0
m_Controller: {fileID: 9100000}
- m_Name: standTrig
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 1
m_Controller: {fileID: 9100000}
- m_Name: waveTrigger
- m_Name: standTrigger
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
@@ -236,31 +227,6 @@ AnimatorState:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1101 &3498771613915995529
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: waveTrigger
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 7205364625675609378}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0.25
m_TransitionOffset: 0
m_ExitTime: 0.875
m_HasExitTime: 0
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!1101 &3764339850583790826
AnimatorStateTransition:
m_ObjectHideFlags: 1
@@ -270,7 +236,7 @@ AnimatorStateTransition:
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: standTrig
m_ConditionEvent: standTrigger
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 9049851607463686061}
@@ -298,7 +264,6 @@ AnimatorState:
m_CycleOffset: 0
m_Transitions:
- {fileID: -1204995913918529780}
- {fileID: 3498771613915995529}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
@@ -314,32 +279,6 @@ AnimatorState:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &7205364625675609378
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Waving
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: -203655887218126122, guid: ca6806f4c66ad464bacd03026cbbdc21, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1109 &7209319973625494105
AnimatorTransition:
m_ObjectHideFlags: 1