Files
my-project/Assets/charecter-controller/scripts/charecter.cs
2026-04-15 02:56:11 +05:00

190 lines
6.8 KiB
C#

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;
// 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<CharacterController>();
_anim = GetComponentInChildren<Animator>();
Cursor.lockState = CursorLockMode.Locked;
_bodyYaw = transform.eulerAngles.y;
_headYaw = _bodyYaw;
_headBindPose = head.localRotation;
}
void Update()
{
HandleLook();
HandleMovement();
HandlePickup();
}
// ── Item Pickup ───────────────────────────────────────────────────────────
void HandlePickup()
{
if (Input.GetKeyDown(KeyCode.E))
{
TryPickupNearbyItem();
}
}
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<WorldItem>();
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()
{
_headYaw += Input.GetAxis("Mouse X") * mouseSensitivity;
_pitch -= Input.GetAxis("Mouse Y") * mouseSensitivity;
_pitch = Mathf.Clamp(_pitch, -maxPitch, maxPitch);
}
// ── Movement ──────────────────────────────────────────────────────────────
void HandleMovement()
{
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
bool isCrouching = Input.GetKey(KeyCode.C);
bool isRunning = 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 (Input.GetButtonDown("Jump") && !isCrouching)
{
_verticalVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity);
_anim?.SetTrigger(HashJump);
}
}
_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;
}
}