update di chuyển debug jump

This commit is contained in:
2026-05-30 11:20:59 +07:00
parent ee8e633043
commit dfcf8c1c25
26 changed files with 2716 additions and 219 deletions

View File

@@ -9,46 +9,153 @@ namespace OnlyScove.Scripts
[SerializeField] private string speedParamName = "Speed";
[SerializeField] private string velocityXParamName = "Velocity X";
[SerializeField] private string velocityZParamName = "Velocity Z";
[SerializeField] private string groundedParamName = "Grounded";
[SerializeField] private float animationDamping = 0.2f;
[Header("Visual Correction")]
[SerializeField] private float visualOffsetY = 0f;
[SerializeField] private Transform modelTransform;
private CharacterController controller;
private Animator anim;
private int speedHash;
private int velocityXHash;
private int velocityZHash;
private bool hasSpeedParam;
private bool hasVelocityXParam;
private bool hasVelocityZParam;
private int groundedHash;
private readonly System.Collections.Generic.HashSet<int> parameterHashes = new System.Collections.Generic.HashSet<int>();
public void Initialize(Animator animator)
{
this.anim = animator;
this.controller = GetComponentInParent<CharacterController>();
// Auto-assign modelTransform if null
if (modelTransform == null && anim != null) modelTransform = anim.transform;
if (anim != null)
{
Debug.Log($"<color=green>[AnimationHandler]</color> Animator found on: {anim.gameObject.name}");
parameterHashes.Clear();
foreach (AnimatorControllerParameter param in anim.parameters)
{
if (param.name == speedParamName) hasSpeedParam = true;
if (param.name == velocityXParamName) hasVelocityXParam = true;
if (param.name == velocityZParamName) hasVelocityZParam = true;
parameterHashes.Add(param.nameHash);
}
int speedHashCheck = Animator.StringToHash(speedParamName);
if (!parameterHashes.Contains(speedHashCheck) && parameterHashes.Contains(Animator.StringToHash("Blend")))
{
speedParamName = "Blend";
speedHash = Animator.StringToHash(speedParamName);
Debug.Log($"<color=yellow>[AnimationHandler]</color> 'Speed' not found, using 'Blend' instead.");
}
}
else
{
Debug.LogError("<color=red>[AnimationHandler]</color> FAILED to find Animator! Please check your Prefab.");
}
speedHash = Animator.StringToHash(speedParamName);
velocityXHash = Animator.StringToHash(velocityXParamName);
velocityZHash = Animator.StringToHash(velocityZParamName);
groundedHash = Animator.StringToHash(groundedParamName);
}
public void UpdateAnimator(float speed, Vector2 moveInput, float deltaTime)
private bool wasGroundedInAnimator;
public void UpdateAnimator(float speed, Vector2 moveInput, bool isGrounded, float deltaTime)
{
if (anim == null) return;
if (hasSpeedParam) anim.SetFloat(speedHash, speed, animationDamping, deltaTime);
if (hasVelocityXParam) anim.SetFloat(velocityXHash, moveInput.x * speed, animationDamping, deltaTime);
if (hasVelocityZParam) anim.SetFloat(velocityZHash, moveInput.y * speed, animationDamping, deltaTime);
// Snap to zero if speed is very low to force Idle
float targetSpeed = speed < 0.05f ? 0f : speed;
float damping = (targetSpeed == 0f || targetSpeed > 0.9f) ? 0f : animationDamping;
if (parameterHashes.Contains(speedHash)) anim.SetFloat(speedHash, targetSpeed, damping, deltaTime);
if (parameterHashes.Contains(velocityXHash)) anim.SetFloat(velocityXHash, moveInput.x * targetSpeed, damping, deltaTime);
if (parameterHashes.Contains(velocityZHash)) anim.SetFloat(velocityZHash, moveInput.y * targetSpeed, damping, deltaTime);
// Quan trọng: Cập nhật biến Grounded cho Animator
if (parameterHashes.Contains(groundedHash)) anim.SetBool(groundedHash, isGrounded);
// Nếu đang ở trên mặt đất, đảm bảo reset các trạng thái nhảy/rơi
if (isGrounded)
{
SafeSetBool("IsJumping", false);
SafeSetBool("IsFalling", false);
var stateInfo = anim.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName("Jump") || stateInfo.IsName("Fall") || stateInfo.IsName("Airborne"))
{
anim.CrossFadeInFixedTime("Locomotion Ground", 0.1f);
}
}
wasGroundedInAnimator = isGrounded;
}
public void SafeSetTrigger(string name)
{
if (anim == null) return;
int hash = Animator.StringToHash(name);
if (parameterHashes.Contains(hash)) anim.SetTrigger(hash);
}
public void SafeSetTrigger(int hash)
{
if (anim == null) return;
if (parameterHashes.Contains(hash)) anim.SetTrigger(hash);
}
public void SafeResetTrigger(string name)
{
if (anim == null) return;
int hash = Animator.StringToHash(name);
if (parameterHashes.Contains(hash)) anim.ResetTrigger(hash);
}
public void SafeResetTrigger(int hash)
{
if (anim == null) return;
if (parameterHashes.Contains(hash)) anim.ResetTrigger(hash);
}
public void SafeSetBool(string name, bool value)
{
if (anim == null) return;
int hash = Animator.StringToHash(name);
if (parameterHashes.Contains(hash)) anim.SetBool(hash, value);
}
public void SafeSetFloat(int hash, float value, float dampTime, float deltaTime)
{
if (anim == null) return;
if (parameterHashes.Contains(hash)) anim.SetFloat(hash, value, dampTime, deltaTime);
}
public void SetSpeed(float speed)
{
if (anim != null && hasSpeedParam) anim.SetFloat(speedHash, speed);
if (anim != null && parameterHashes.Contains(speedHash))
anim.SetFloat(speedHash, speed);
}
public void ForceLocomotion()
{
if (anim != null) anim.CrossFadeInFixedTime("Locomotion Ground", 0.1f);
}
private void LateUpdate()
{
if (modelTransform != null && controller != null)
{
// Automatically snap mesh to the bottom of the CharacterController capsule
// This fixes hovering/tiptoeing issues regardless of animation offsets
Vector3 targetPos = modelTransform.localPosition;
float bottomY = controller.center.y - (controller.height / 2f);
targetPos.y = bottomY + visualOffsetY;
modelTransform.localPosition = targetPos;
}
}
}
}