using System.Collections; using UnityEngine; using UnityEngine.Events; using UnityEngine.Serialization; namespace Invector.vCharacterController.vActions { [vClassHeader("Trigger Generic Action", false, iconName = "triggerIcon")] public class vTriggerGenericAction : vMonoBehaviour { [vEditorToolbar("Input", order = 1)] public InputType inputType = InputType.GetButtonDown; [Tooltip("Input to make the action")] public GenericInput actionInput = new GenericInput("E", "A", "A"); public enum InputType { GetButtonDown, GetDoubleButton, GetButtonTimer, AutoAction }; [vHelpBox("Time you have to hold the button *Only for GetButtonTimer*")] public float buttonTimer = 3f; [vHelpBox("Add delay to start the input count *Only for GetButtonTimer*")] public float inputDelay = 0.1f; [vHelpBox("*Only for GetButtonTimer* \n\nTRUE: Play the animation while you're holding the button \n" + "FALSE: Play the animation after you finish holding the button")] public bool playAnimationWhileHoldingButton = true; [vHelpBox("Time to press the button twice *Only for GetDoubleButton*")] public float doubleButtomTime = 0.25f; [vEditorToolbar("Trigger", order = 2)] public string actionName = "Action"; public string actionTag = "Action"; [vHelpBox("Disable this trigger OnStart")] public bool disableOnStart = false; [vHelpBox("Disable the Player's Capsule Collider Collision, useful for animations with closer interactions")] public bool disableCollision; [vHelpBox("Disable the Player's Rigidbody Gravity, useful for on air animations")] public bool disableGravity; [vHelpBox("It will only use the trigger if the forward of the character is close to the forward of this transform")] public bool activeFromForward; [vHelpBox("Max angle between character forward and trigger forward to active trigger"), Range(5, 180)] public float forwardAngle = 55; [vHelpBox("Rotate Character to the Forward Rotation of this Trigger")] public bool useTriggerRotation; [vHelpBox("Destroy this Trigger after pressing the Input or AutoAction or finishing the Action")] public bool destroyAfter = false; [vHideInInspector("destroyAfter")] public float destroyDelay = 0f; [vHelpBox("Change your CameraState to a Custom State while playing the animation")] public string customCameraState; [vEditorToolbar("Animation", order = 2)] [vHelpBox("Trigger a Animation - Use the exactly same name of the AnimationState you want to trigger, " + "don't forget to add a vAnimatorTag to your State")] public string playAnimation; public float crossFadeTransition = 0.25f; public int animatorLayer = 0; [vHelpBox("Check the Exit Time of your animation (if it doesn't loop) and insert here. \n\n" + "For example if your Exit Time is 0.82 you need to insert 0.82" + "\n\nAlways check with the Debug of the GenericAction if your animation is finishing correctly, " + "otherwise the controller won't reset to the default physics and collision.", vHelpBoxAttribute.MessageType.Warning)] [Tooltip("You can use this to make a persistent action, and finish the action calling FinishAction method of the vGenericAction component in your character")] public bool endActionManualy = false; [vHideInInspector("endActionManualy",invertValue =true)] public float endExitTimeAnimation = 0.8f; [vHelpBox("Use a ActionState value to apply special conditions for your AnimatorController transitions")] public int animatorActionState = 0; [vHelpBox("Reset the ActionState parameter to 0 after playing the animation")] public bool resetAnimatorActionState = true; [vHelpBox("Use a empty transform as reference for the MatchTarget")] public Transform matchTarget; [vHelpBox("Select the bone you want to use as reference to the Match Target")] public AvatarTarget avatarTarget; [Header("Curve Match target system")] public bool useLocalX = false; public bool useLocalZ = true; public AnimationCurve matchPositionXZCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(.5f, 1), new Keyframe(1, 1)); public AnimationCurve matchPositionYCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(.5f, 1), new Keyframe(1, 1)); public AnimationCurve matchRotationCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(.5f, 1), new Keyframe(1, 1)); [vEditorToolbar("Events", order = 3)] [Tooltip("Delay to run the OnDoAction Event")] [FormerlySerializedAs("onDoActionDelay")] public float onPressActionDelay; [Header("--- INPUT EVENTS ---")] [FormerlySerializedAs("OnDoAction")] public UnityEvent OnPressActionInput; public OnDoActionWithTarget onPressActionInputWithTarget; [Header("--- ONLY FOR GET BUTTON TIMER ---")] public UnityEvent OnCancelActionInput; public UnityEvent OnFinishActionInput; public OnUpdateValue OnUpdateButtonTimer; [Header("--- ANIMATION EVENTS ---")] public UnityEvent OnStartAnimation; public UnityEvent OnEndAnimation; [Header("--- PLAYER AND TRIGGER DETECTION ---")] public OnDoActionWithTarget OnPlayerEnter; public OnDoActionWithTarget OnPlayerStay; public OnDoActionWithTarget OnPlayerExit; [Header("--- ACTION VALIDATION ---")] public OnDoActionWithTarget OnValidate; public OnDoActionWithTarget OnInvalidate; private float currentButtonTimer; internal Collider _collider; protected virtual void Start() { this.gameObject.tag = actionTag; this.gameObject.layer = LayerMask.NameToLayer("Triggers"); _collider = GetComponent(); _collider.isTrigger = true; if (disableOnStart) this.enabled = false; } public virtual IEnumerator OnPressActionDelay(GameObject obj) { yield return new WaitForSeconds(onPressActionDelay); OnPressActionInput.Invoke(); if (obj) onPressActionInputWithTarget.Invoke(obj); } public void UpdateButtonTimer(float value) { if (value != currentButtonTimer) { currentButtonTimer = value; OnUpdateButtonTimer.Invoke(value); } } [System.Serializable] public class OnUpdateValue : UnityEvent { } } [System.Serializable] public class OnDoActionWithTarget : UnityEvent { } }