using UnityEngine; [RequireComponent(typeof(CharacterController))] public class charecter : MonoBehaviour { [Header("Movement")] public float walkSpeed = 5f; public float runSpeed = 9f; public float crouchSpeed = 2.5f; public float jumpHeight = 1.5f; public float gravity = -9.81f; [Header("References")] [Tooltip("Head BONE of the character.")] public Transform head; [Header("Look")] public float mouseSensitivity = 2f; public float maxPitch = 80f; [Header("Body Turn")] public float maxHeadYaw = 60f; public float bodyAlignSpeed = 300f; // ── private ────────────────────────────────────────────────────────────── CharacterController _cc; Animator _anim; float _verticalVelocity; float _bodyYaw; float _headYaw; float _pitch; Quaternion _headBindPose; bool _jumpRequested = false; // Animator parameter hashes — no hardcoded strings at runtime static readonly int HashSpeed = Animator.StringToHash("Speed"); static readonly int HashIsMoving = Animator.StringToHash("IsMoving"); static readonly int HashIsCrouching = Animator.StringToHash("IsCrouching"); static readonly int HashIsGrounded = Animator.StringToHash("IsGrounded"); static readonly int HashJump = Animator.StringToHash("Jump"); // ── Unity lifecycle ─────────────────────────────────────────────────────── void Start() { _cc = GetComponent(); _anim = GetComponentInChildren(); Cursor.lockState = CursorLockMode.Locked; _bodyYaw = transform.eulerAngles.y; _headYaw = _bodyYaw; _headBindPose = head.localRotation; // Ensure PlayerInput exists and subscribe to events if (PlayerInput.Instance == null) { var go = new GameObject("PlayerInput"); go.AddComponent(); } PlayerInput.Instance.OnPickupPressed += () => TryPickupNearbyItem(); PlayerInput.Instance.OnJumpPressed += () => { _jumpRequested = true; }; } void Update() { HandleLook(); HandleMovement(); } // ── Item Pickup ─────────────────────────────────────────────────────────── void HandlePickup() { // Input moved to PlayerInput events } void TryPickupNearbyItem() { float pickupRadius = 2.5f; Collider[] colliders = Physics.OverlapSphere(transform.position, pickupRadius); Debug.Log($"[Pickup] Checking {colliders.Length} colliders in radius {pickupRadius}"); WorldItem closestItem = null; float closestDist = float.MaxValue; foreach (var col in colliders) { var worldItem = col.GetComponent(); if (worldItem != null) { float dist = Vector3.Distance(transform.position, worldItem.transform.position); Debug.Log($"[Pickup] Found WorldItem: {worldItem.itemData?.itemName ?? "null"} at dist {dist}"); if (dist < closestDist) { closestDist = dist; closestItem = worldItem; } } } if (closestItem != null) { Debug.Log($"[Pickup] Trying to pick up: {closestItem.itemData?.itemName}"); bool pickedUp = closestItem.TryPickupByButton(); if (pickedUp) { Debug.Log($"Picked up: {closestItem.itemData.itemName}"); } } else { Debug.Log("[Pickup] No WorldItem found nearby"); } } void LateUpdate() { ApplyRotations(); } // ── Mouse look ──────────────────────────────────────────────────────────── void HandleLook() { var input = PlayerInput.Instance; if (input != null) { _headYaw += input.MouseX * mouseSensitivity; _pitch -= input.MouseY * mouseSensitivity; } _pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch); } // ── Movement ────────────────────────────────────────────────────────────── void HandleMovement() { var input = PlayerInput.Instance; float h = input != null ? input.Horizontal : Input.GetAxisRaw("Horizontal"); float v = input != null ? input.Vertical : Input.GetAxisRaw("Vertical"); bool isCrouching = input != null ? input.Crouch : Input.GetKey(KeyCode.C); bool isRunning = input != null ? input.Run && !isCrouching : Input.GetKey(KeyCode.LeftShift) && !isCrouching; bool isMoving = (h * h + v * v) > 0.01f; float speed = isCrouching ? crouchSpeed : isRunning ? runSpeed : walkSpeed; // Body aligns toward camera when moving if (isMoving) _bodyYaw = Mathf.MoveTowardsAngle(_bodyYaw, _headYaw, bodyAlignSpeed * Time.deltaTime); // Head-drag float offset = Mathf.DeltaAngle(_bodyYaw, _headYaw); float clampedOffset = Mathf.Clamp(offset, -maxHeadYaw, maxHeadYaw); _bodyYaw += offset - clampedOffset; _headYaw = _bodyYaw + clampedOffset; // Jump if (_cc.isGrounded) { if (_verticalVelocity < 0f) _verticalVelocity = -2f; if (_jumpRequested && !isCrouching) { _verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity); _anim?.SetTrigger(HashJump); } _jumpRequested = false; } _verticalVelocity += gravity * Time.deltaTime; // Move Quaternion headRot = Quaternion.Euler(0f, _headYaw, 0f); Vector3 moveDir = (headRot * Vector3.forward * v + headRot * Vector3.right * h).normalized; moveDir.y = _verticalVelocity; _cc.Move(moveDir * speed * Time.deltaTime); // Animator params if (_anim != null) { // Speed: 0 = idle, 0.5 = walk, 1 = run float animSpeed = !isMoving ? 0f : isRunning ? 1f : 0.5f; _anim.SetFloat(HashSpeed, animSpeed, 0.1f, Time.deltaTime); _anim.SetBool (HashIsMoving, isMoving); _anim.SetBool (HashIsCrouching, isCrouching); _anim.SetBool (HashIsGrounded, _cc.isGrounded); } } // ── Apply bone rotations ────────────────────────────────────────────────── void ApplyRotations() { transform.rotation = Quaternion.Euler(0f, _bodyYaw, 0f); float headOffset = Mathf.DeltaAngle(_bodyYaw, _headYaw); Quaternion yawRot = Quaternion.Euler(0f, headOffset, 0f); Quaternion pitchRot = Quaternion.Euler(_pitch, 0f, 0f); head.localRotation = _headBindPose * yawRot * pitchRot; } }