Inspect ability

galamot

New member
Hi, I'm using the third person controller and I was wondering if there's any easy solution to make an "Inspect ability" where the character can trigger a UI with custom text that tells you "the door is locked" or something like that. Thank you :)
 
Here's a boilerplate.
On the object add this script...
C#:
using UnityEngine;

public class Inspectable : MonoBehaviour, IInspectable
{
    [Tooltip("The unique Animator identifier of the inspectable.")]
    [SerializeField] protected int m_AnimatorID = 0;
    [Tooltip("The name that the ability will display when the hint is shown")]
    [SerializeField] protected string m_HintDisplayName = "Inspectable";
    public int AnimatorID => m_AnimatorID;
    public string HintDisplayName => m_HintDisplayName;
    private Animator m_ObjectAnimator;
    private static int s_InspectTriggerParameter = Animator.StringToHash("Inspect");
    private static int s_InspectBoolParameter = Animator.StringToHash("IsInspecting");

    private void Awake()
    {
        m_ObjectAnimator = GetComponent<Animator>();
    }
    public void Inspect(bool isInspecting)
    {
        if (m_ObjectAnimator)
        {
            m_ObjectAnimator.SetBool(s_InspectBoolParameter, isInspecting);
            m_ObjectAnimator.SetTrigger(s_InspectTriggerParameter);
        }
    }
}

On the character add this ability...

C#:
using Opsive.Shared.Events;
using Opsive.Shared.Game;
using Opsive.UltimateCharacterController.Character.Abilities;
using UnityEngine;

[DefaultAbilityIndex(74)]
[DefaultState("Inspect")]
[DefaultInputName("Action")]
[DefaultStartType(AbilityStartType.ButtonDown)]
[DefaultStopType(AbilityStopType.ButtonToggle)]
public class Inspect : DetectObjectAbilityBase
{
    [Tooltip("You can use an animation event to stop the Ability")]
    [SerializeField] protected bool m_UseAnimationEvents = false;
    [Tooltip("You can use a timer to stop the Ability if not using animation events")]
    [SerializeField] protected float m_DefaultInspectTime = 3f;
    private float m_StopTime = 0;
    private IInspectable m_Inspectable;
    public enum InspectState { Inspecting, Finished }
    private InspectState m_InspectState = InspectState.Finished;
    public override int AbilityIntData => m_Inspectable.AnimatorID + (int)m_InspectState;

    public override void Awake()
    {
        base.Awake();
        EventHandler.RegisterEvent(m_GameObject, "OnStartInspectObject", OnStartInspecting);
        EventHandler.RegisterEvent(m_GameObject, "OnStopInspectObject", OnStopInspecting);
    }
    public override void OnDestroy()
    {
        EventHandler.RegisterEvent(m_GameObject, "OnStartInspectObject", OnStartInspecting);
        EventHandler.RegisterEvent(m_GameObject, "OnStopInspectObject", OnStopInspecting);
        base.OnDestroy();
    }

    /// <summary>
    /// Validates the object to ensure it is valid for the current ability.
    /// </summary>
    /// <param name="obj">The object being validated.</param>
    /// <param name="raycastHit">The raycast hit of the detected object. Will be null for trigger detections.</param>
    /// <returns>True if the object is valid. The object may not be valid if it doesn't have an ability-specific component attached.</returns>
    protected override bool ValidateObject(GameObject obj, RaycastHit? raycastHit)
    {
        if (!base.ValidateObject(obj, raycastHit))
            return false;

        m_Inspectable = obj.GetCachedParentComponent<IInspectable>();
        Debug.Log(m_Inspectable);
        if (m_Inspectable == null)
            return false;
        m_AbilityMessageText = "Press 'Action' button to inspect " + m_Inspectable.HintDisplayName;
        return true;
    }
    public override bool ShouldBlockAbilityStart(Ability startingAbility)
    {
        return true;
    }
    public override bool ShouldStopActiveAbility(Ability activeAbility)
    {
        return true;
    }
    public override bool CanStartAbility()
    {
        return base.CanStartAbility();
    }
    protected override void AbilityStarted()
    {
        base.AbilityStarted();
        m_InspectState = InspectState.Inspecting;
        m_CharacterLocomotion.UpdateAbilityAnimatorParameters();
        if (m_UseAnimationEvents == false)
        {
            m_StopTime = Time.time + m_DefaultInspectTime;
            OnStartInspecting();
        }
    }
    private void OnStartInspecting()
    {
        m_Inspectable.Inspect(true);
    }
    public override bool CanStopAbility()
    {
        return m_InspectState == InspectState.Finished;
    }
    protected override void AbilityStopped(bool force)
    {
        if (force)
        {
            m_InspectState = InspectState.Finished;
            m_Inspectable.Inspect(false);
        }
        base.AbilityStopped(force);
    }

    public override void Update()
    {
        if (m_UseAnimationEvents == false && m_InspectState == InspectState.Inspecting && Time.time > m_StopTime)
            OnStopInspecting();
    }

    private void OnStopInspecting()
    {
        m_InspectState = InspectState.Finished;
        m_CharacterLocomotion.UpdateAbilityAnimatorParameters();
        m_Inspectable.Inspect(false);
        StopAbility();
    }
}


and you'll need this interface in your project...

C#:
public interface IInspectable
{
    /// <summary>
    /// The unique identifier of the object. This value is used within the AbilityIntData parameter of the character's animator.
    /// </summary>
    int AnimatorID { get; }
   
    /// <summary>
    /// The hint text string that should be shown to notify the player of the interactable
    /// </summary>
    string HintDisplayName { get; }

    void Inspect(bool isInspecting);
}

Nothing flash but should get you started.
 
Oh and you'll need to set the Ability Message Text in the editor to some value other than null. It will not show the text otherwise.
 
Awesome !! It's technically working however the bool is working the opposite way, the UI turns on when approaching the object as usual, and disappears when interacted. How could I reverse it? Also got any idea on how could I have a different UI text for the inspect message and the interact message & icon? Thank you very mucho.
 
You could have the animator or camera setup to look at the object when it starts, or have some ui monitor on the canvas display. You'll need to make up ui and add the function to the script
 
Top