using System.Collections; using UnityEngine; using UnityEngine.EventSystems; namespace BulletHellTemplate { /// /// This script allows rotation of a child object inside a container when dragging or holding, /// or triggers an animation on click without dragging. /// Attach this script to an Image or Button (set to transparent). /// public class DragRotateAndHit : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler { public static DragRotateAndHit Singleton; [Header("Container Settings")] [Tooltip("The container that holds the child object to be rotated.")] public Transform container; [Tooltip("Rotation speed of the container.")] public float rotateSpeed = 4f; [Tooltip("Audio clip to play when triggering a hit animation.")] public AudioClip hitClip; [Tooltip("Audio mixer tag to identify the audio group.")] public string hitTag = "master"; private Animator childAnimator; private CharacterModel childCharacterModel; private bool isDragging = false; private bool isHolding = false; private Vector2 startPointerPosition; private Quaternion initialRotation; private void Awake() { if (Singleton == null) { Singleton = this; } else { Destroy(gameObject); } } private void Start() { SetupChild(); } /// /// Sets up the child object inside the container and retrieves its Animator and/or CharacterModel. /// private void SetupChild() { if (container == null) { Debug.LogError("No container assigned. Please assign a container in the inspector."); return; } if (container.childCount > 0) { Transform child = container.GetChild(0); childAnimator = child.GetComponent(); childCharacterModel = child.GetComponent(); if (childAnimator == null && childCharacterModel == null) { Debug.LogError("No Animator or CharacterModel found in the child of the container."); } } else { Debug.LogError("No child found in the container."); } initialRotation = container.rotation; } /// /// Called when the pointer is pressed down on the UI element. /// public void OnPointerDown(PointerEventData eventData) { startPointerPosition = eventData.position; isDragging = false; isHolding = true; } /// /// Called when dragging the UI element. Rotates the container based on horizontal drag movement. /// /// Pointer event data containing the drag information. public void OnDrag(PointerEventData eventData) { if (container == null || container.childCount == 0) return; Vector2 dragDirection = eventData.position - startPointerPosition; if (dragDirection.x != 0) { float rotationAmount = -rotateSpeed * dragDirection.x * Time.deltaTime; container.Rotate(Vector3.up, rotationAmount); } isDragging = true; } private void Update() { // If holding but not dragging, rotate the container slowly if (isHolding && !isDragging) { container.Rotate(Vector3.up, rotateSpeed * Time.deltaTime); } } /// /// Called when the pointer is released. If not dragging, triggers the hit animation. /// /// Pointer event data. public void OnPointerUp(PointerEventData eventData) { isHolding = false; // If it was not dragging, trigger a "Hit" animation if (!isDragging) { // Play audio if available if (AudioManager.Singleton != null) { AudioManager.Singleton.PlayAudio(hitClip, hitTag); } // Check if the child has a CharacterModel with Playable animations if (childCharacterModel != null && childCharacterModel.usePlayableAnimations) { childCharacterModel.PlayBaseAnimation("Hit"); } // Otherwise, fallback to the legacy Animator else if (childAnimator != null) { childAnimator.SetTrigger("hit"); } else { Debug.LogWarning("No Animator or CharacterModel found to trigger the hit animation."); } } } /// /// Resets the container rotation to its original state. /// public void ResetRotation() { if (container != null) { container.rotation = initialRotation; } else { Debug.LogError("No container assigned to reset rotation."); } } /// /// Updates the character after a new one is loaded into the container. /// public void UpdateCharacter() { StartCoroutine(UpdateCharacterAfterFrame()); } /// /// Waits a frame to ensure the new character is instantiated before setup. /// private IEnumerator UpdateCharacterAfterFrame() { yield return null; ResetRotation(); SetupChild(); if (childAnimator == null && childCharacterModel == null) { Debug.LogError("No Animator or CharacterModel found after character update. Check the container's child."); } } } }