using UnityEngine; using UnityEngine.InputSystem; namespace StudyCase3 { public enum PickMode { RayCast, Mouse } public class ThirdCharacterController : MonoBehaviour { [Header("MoveSettings")] CharacterController characterController; InputActionAsset inputAction; Animator animator; Transform forward; Transform model; Cinemachine.CinemachineVirtualCamera vCam; public float moveSpeed = 5f; public float jumpSpeed = 2f; public float turnSpeed = 10f; public float gravity = 10f; Vector3 moveDir; Vector2 moveInput; [Header("PickSettings")] public PickMode pickMode = PickMode.RayCast; public CursorLockMode cursorLock; public bool useDrawRay = true; public float maxDistance = 5f; public LayerMask layerMask; public float itemsRotateSpeed = 120f; public Transform itemRoot; Item selectItem; LineRenderer lineRenderer; private void Awake() { Cursor.lockState = cursorLock; characterController = GetComponent(); forward = transform.Find("Forward"); model = transform.Find("Model"); animator = model.GetComponentInChildren(); vCam = transform.Find("Virtual Camera").GetComponent(); inputAction = Resources.Load("PlayerInputActions"); inputAction.FindAction("Move").started += OnMove; inputAction.FindAction("Move").performed += OnMove; inputAction.FindAction("Move").canceled += OnMove; inputAction.FindAction("Jump").performed += OnJump; inputAction.FindAction("Pick").performed += OnPickUp; inputAction.Enable(); itemRoot = transform.Find("ItemRoot"); if (lineRenderer == null) { lineRenderer = gameObject.AddComponent(); lineRenderer.material = new Material(Shader.Find("Universal Render Pipeline/2D/Sprite-Unlit-Default")); lineRenderer.useWorldSpace = true; } } private void Update() { Move(); CheckRayHit(); ItemsRotate(); } public void OnMove(InputAction.CallbackContext context) { if (characterController.isGrounded) moveInput = context.ReadValue(); else moveInput = Vector2.zero; } public void OnJump(InputAction.CallbackContext context) { if (context.performed && characterController.isGrounded) { moveDir.y = jumpSpeed; } } void Move() { moveDir = new Vector3(moveInput.x, moveDir.y, moveInput.y); forward.eulerAngles = new Vector3(0, vCam.transform.eulerAngles.y, 0); moveDir = forward.TransformDirection(moveDir); if (moveInput != Vector2.zero) { animator?.SetBool("Move", true); Quaternion target = Quaternion.LookRotation(new Vector3(moveDir.x, 0, moveDir.z)); model.rotation = Quaternion.Slerp(model.rotation, target, turnSpeed * Time.deltaTime); } else animator?.SetBool("Move", false); if (!characterController.isGrounded) moveDir.y -= gravity * Time.deltaTime; characterController.Move(moveDir * moveSpeed * Time.deltaTime); } #region PickUp public void OnPickUp(InputAction.CallbackContext context) { if (pickMode != PickMode.RayCast) return; if (selectItem != null) selectItem.PickUp(itemRoot); selectItem = null; } void CheckRayHit() { lineRenderer.enabled = useDrawRay; if (pickMode != PickMode.RayCast) { useDrawRay = false; return; } Ray ray = new Ray(model.position, model.forward); RaycastHit hit; if (Physics.Raycast(ray, out hit, maxDistance, layerMask)) { DrawRay(model.position, hit.point, new Color(0, 1, 1)); Item curItem = hit.transform.GetComponent(); if (curItem != null && curItem != selectItem) { if (selectItem != null) selectItem.UnSelect(); selectItem = curItem; selectItem.Select(); } } else { DrawRay(model.position, model.position+ model.forward* maxDistance, new Color(1, 1, 1)); if (selectItem != null) selectItem.UnSelect(); selectItem = null; } } void DrawRay(Vector3 startPos, Vector3 endPos, Color color) { lineRenderer.startColor = lineRenderer.endColor = color; lineRenderer.startWidth = lineRenderer.endWidth = 0.1f; lineRenderer.positionCount = 2; lineRenderer.SetPosition(0, startPos); lineRenderer.SetPosition(1, endPos); lineRenderer.enabled = true; } void ItemsRotate() { itemRoot.Rotate(0,itemsRotateSpeed*Time.deltaTime, 0); } public void SetItems() { float radius = 1.5f; float angleStep = 360 / itemRoot.childCount; for (int i = 0; i < itemRoot.childCount; i++) { Transform item = itemRoot.GetChild(i); float angle = angleStep * i; Quaternion rot = Quaternion.Euler(0, angle, 0); item.localPosition = rot * itemRoot.forward * radius; item.localScale = Vector3.one * 0.1f; } } #endregion } }